Оскільки ви, мабуть, використовуєте SQL Server 2016, я хотів би викинути ще один " можливий " варіант - SESSION_CONTEXT
.
У статті Леонарда Лобеля « Спільний доступ у SQL Server 2016»SESSION_CONTEXT
є дуже хороша інформація про цю нову функціональність у SQL Server 2016.
Узагальнення деяких ключових моментів:
Якщо ви коли-небудь хотіли поділитися станом сеансу для всіх збережених процедур і пакетів протягом усього життя з'єднання з базою даних, вам сподобається SESSION_CONTEXT
. Коли ви підключаєтесь до SQL Server 2016, ви отримуєте словник, що складається із станів, або те, що часто називають мішком стану, десь там, де ви можете зберігати значення, наприклад, рядки та числа, а потім отримувати його за допомогою ключа, який ви призначите. У випадку з SESSION_CONTEXT
ключем є будь-який рядок, а значення - sql_variant, тобто він може вміщувати різні типи.
Щойно ви щось зберігаєте SESSION_CONTEXT
, він залишається там, поки з'єднання не закриється. Він не зберігається в жодній таблиці в базі даних, він просто живе в пам'яті до тих пір, поки з'єднання залишається живим. І будь-який і весь код T-SQL, який працює всередині збережених процедур, тригерів, функцій чи будь-чого іншого, може ділитися тим, у що ви потрапляєте
SESSION_CONTEXT
.
Найближче подібне, що у нас було до цього часу CONTEXT_INFO
, - це дозволяє зберігати та ділити одне бінарне значення довжиною до 128 байт, що набагато менш гнучко, ніж словник, який ви отримуєте SESSION_CONTEXT
, який підтримує декілька значень різних даних типи.
SESSION_CONTEXT
проста у використанні, просто зателефонуйте sp_set_session_context, щоб зберегти значення потрібною клавішею. Коли ви це зробите, ви вводите ключ і значення звичайно, але ви також можете встановити параметр read_only на значення true. Це блокує значення в контексті сеансу, так що воно не може бути змінено протягом усього часу з'єднання. Так, наприклад, клієнтській програмі легко викликати цю збережену процедуру, щоб встановити деякі значення контексту сеансу відразу після встановлення з'єднання з базою даних. Якщо програма встановлює параметр read_only, коли це робить, то збережені процедури та інший код T-SQL, який потім виконується на сервері, можуть зчитувати лише значення, вони не можуть змінити те, що було встановлено програмою, що працює на клієнті.
Як тест, я створив тригер входу в сервер, який задає певну CONTEXT_SESSION
інформацію - для однієї з них SESSION_CONTEXT
було встановлено @read_only
.
DROP TRIGGER IF EXISTS [InitializeSessionContext] ON ALL SERVER
GO
CREATE TRIGGER InitializeSessionContext ON ALL SERVER
FOR LOGON AS
BEGIN
--Initialize context information that can be altered in the session
EXEC sp_set_session_context @key = N'UsRegion'
,@value = N'Southeast'
--Initialize context information that cannot be altered in the session
EXEC sp_set_session_context @key = N'CannotChange'
,@value = N'CannotChangeThisValue'
,@read_only = 1
END;
Я ввійшов як абсолютно новий користувач і зміг отримати SESSION_CONTEXT
інформацію:
DECLARE @UsRegion varchar(20)
SET @UsRegion = CONVERT(varchar(20), SESSION_CONTEXT(N'UsRegion'))
SELECT DoThat = @UsRegion
DECLARE @CannotChange varchar(20)
SET @CannotChange = CONVERT(varchar(20), SESSION_CONTEXT(N'CannotChange'))
SELECT DoThat = @CannotChange
Я навіть намагався змінити інформацію про контекст "read_only":
EXEC sp_set_session_context @key = N'CannotChange'
,@value = N'CannotChangeThisValue'
і отримали помилку:
Повідомлення 15664, Рівень 16, Стан 1, Процедура sp_set_session_context, Рядок 1 [Початкова лінія рядка 8] Неможливо встановити ключ "CannotChange" у контексті сеансу. Для цього сеансу ключ встановлено як read_only.
Важлива примітка про тригери входу ( з цієї публікації )!
Тригер входу може ефективно запобігти успішному підключенню до Двигуна баз даних для всіх користувачів, включаючи членів ролі фіксованого сервера sysadmin. Коли тригер входу перешкоджає з'єднанням, члени ролі фіксованого сервера sysadmin можуть з'єднуватися за допомогою виділеного з'єднання адміністратора або запускаючи Database Engine в режимі мінімальної конфігурації (-f)
Один з потенційних недоліків полягає в тому, що це заповнює екземпляр контексту сеансу в широкому (не на базі даних). На даний момент я можу придумати лише такі варіанти:
- Назвіть
Session_Context
пари своїх імен-значень, префіксуючи їх ім'ям бази даних, щоб не викликати зіткнення для того ж імені типу в іншій базі даних. Це не вирішує проблему попереднього визначення ВСІХ Session_Context
іменних значень для всіх користувачів.
- Коли спрацьовує тригер входу, у вас є доступ до
EventData
(xml), який ви можете використати для витягування користувача, який здійснює вхід, і виходячи з цього, ви можете створити конкретні Session_Context
пари імен-значення.