Puesto que usted está aparentemente utilizando SQL Server 2016, me gustaría que tirar otra ' posible opción' - SESSION_CONTEXT
.
El artículo de Leonard Lobel, Sharing State in SQL Server 2016 withSESSION_CONTEXT
tiene muy buena información sobre esta nueva funcionalidad en SQL Server 2016.
Resumiendo algunos puntos clave:
Si alguna vez ha querido compartir el estado de la sesión en todos los procedimientos y lotes almacenados durante la vida útil de una conexión de base de datos, le encantará SESSION_CONTEXT
. Cuando se conecta a SQL Server 2016, obtiene un diccionario con estado, o lo que a menudo se conoce como bolsa de estado, un lugar donde puede almacenar valores, como cadenas y números, y luego recuperarlo con una clave que asigne. En el caso de SESSION_CONTEXT
, la clave es cualquier cadena, y el valor es una variable sql_, lo que significa que puede acomodar una variedad de tipos.
Una vez que guarda algo SESSION_CONTEXT
, permanece allí hasta que se cierra la conexión. No se almacena en ninguna tabla de la base de datos, solo vive en la memoria mientras la conexión permanezca activa. Y todos y cada uno de los códigos T-SQL que se ejecutan dentro de procedimientos almacenados, disparadores, funciones o lo que sea, pueden compartir lo que sea que ingreses
SESSION_CONTEXT
.
Lo más parecido a esto que hemos tenido hasta ahora ha sido CONTEXT_INFO
, lo que le permite almacenar y compartir un único valor binario de hasta 128 bytes de longitud, que es mucho menos flexible que el diccionario que obtiene SESSION_CONTEXT
, que admite múltiples valores de datos diferentes tipos.
SESSION_CONTEXT
es fácil de usar, solo llame a sp_set_session_context para almacenar el valor con la clave deseada. Cuando hace eso, proporciona la clave y el valor, por supuesto, pero también puede establecer el parámetro read_only en true. Esto bloquea el valor en el contexto de la sesión, por lo que no se puede cambiar durante el resto de la vida útil de la conexión. Entonces, por ejemplo, es fácil para una aplicación cliente llamar a este procedimiento almacenado para establecer algunos valores de contexto de sesión justo después de establecer la conexión de la base de datos. Si la aplicación establece el parámetro read_only cuando hace esto, los procedimientos almacenados y otro código T-SQL que luego se ejecuta en el servidor solo pueden leer el valor, no pueden cambiar lo que la aplicación ejecutó en el cliente.
Como prueba, creé un disparador de inicio de sesión del servidor que establece cierta CONTEXT_SESSION
información, una de las cuales SESSION_CONTEXT
estaba configurada @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;
Ingresé como usuario completamente nuevo y pude extraer la SESSION_CONTEXT
información:
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
Incluso intenté cambiar la información de contexto 'read_only':
EXEC sp_set_session_context @key = N'CannotChange'
,@value = N'CannotChangeThisValue'
y recibió un error:
Mensaje 15664, Nivel 16, Estado 1, Procedimiento sp_set_session_context, Línea 1 [Batch Start Line 8] No se puede establecer la clave 'CannotChange' en el contexto de la sesión. La clave se ha configurado como read_only para esta sesión.
¡Una nota importante sobre los disparadores de inicio de sesión ( de esta publicación )!
Un desencadenador de inicio de sesión puede prevenir eficazmente las conexiones exitosas al Motor de base de datos para todos los usuarios, incluidos los miembros de la función fija de servidor sysadmin. Cuando un desencadenador de inicio de sesión impide conexiones, los miembros de la función fija de servidor sysadmin pueden conectarse mediante la conexión de administrador dedicada o iniciando el Motor de base de datos en modo de configuración mínima (-f)
Un inconveniente potencial es que esto llena la instancia de contexto de sesión en toda la instancia (no por base de datos). En este punto, las únicas opciones que se me ocurren son:
- Asigne un
Session_Context
nombre a sus pares de nombre-valor prefijándolos con el nombre de la base de datos para no causar una colisión para el mismo tipo de nombre en otra base de datos. Esto no resuelve el problema de predefinir TODOS Session_Context
los valores de nombre para todos los usuarios.
- Cuando se activa el desencadenador de inicio de sesión, tiene acceso a
EventData
(xml) que puede utilizar para extraer el usuario de inicio de sesión y, en función de eso, puede crear Session_Context
pares específicos de nombre-valor.