Поскольку вы, очевидно, используете 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 для этого сеанса.
Важное замечание о триггерах входа в систему ( из этого поста )!
Триггер входа в систему может эффективно предотвратить успешные подключения к компоненту Database Engine для всех пользователей, включая членов предопределенной роли сервера sysadmin. Когда триггер входа в систему запрещает подключения, члены предопределенной роли сервера sysadmin могут подключаться с помощью выделенного подключения администратора или путем запуска компонента Database Engine в режиме минимальной конфигурации (-f)
Один потенциальный недостаток заключается в том, что это заполняет весь экземпляр контекста сеанса (не для базы данных). На данный момент единственные варианты, которые я могу придумать:
- Назовите ваши
Session_Context
пары имя-значение, добавив к ним префикс с именем базы данных, чтобы не вызывать коллизию для того же имени типа в другой базе данных. Это не решает проблему предопределения ВСЕХ Session_Context
значений имен для всех пользователей.
- Когда срабатывает триггер входа в систему, у вас есть доступ к
EventData
(xml), который вы можете использовать для извлечения имени пользователя для входа в систему, и на основании этого вы можете создавать конкретные Session_Context
пары имя-значение.