Como você aparentemente está usando o SQL Server 2016, eu gostaria de jogar outra opção ' possível ' - SESSION_CONTEXT
.
O artigo de Leonard Lobel, Compartilhando Estado no SQL Server 2016,SESSION_CONTEXT
possui algumas informações muito boas sobre essa nova funcionalidade no SQL Server 2016.
Resumindo alguns pontos-chave:
Se você sempre quis compartilhar o estado da sessão entre todos os procedimentos e lotes armazenados durante toda a vida útil de uma conexão com o banco de dados, vai adorar SESSION_CONTEXT
. Quando você se conecta ao SQL Server 2016, obtém um dicionário com estado, ou o que geralmente é chamado de bolsa de estado, algum lugar onde você pode armazenar valores, como seqüências de caracteres e números, e depois recuperá-lo com uma chave que você atribui. No caso de SESSION_CONTEXT
, a chave é qualquer sequência e o valor é uma variável sql_, o que significa que pode acomodar uma variedade de tipos.
Depois de armazenar algo SESSION_CONTEXT
, ele permanece lá até a conexão ser fechada. Ele não é armazenado em nenhuma tabela do banco de dados, apenas permanece na memória enquanto a conexão permanecer ativa. E todo e qualquer código T-SQL executado dentro de procedimentos armazenados, gatilhos, funções ou qualquer outra coisa, pode compartilhar o que você usar
SESSION_CONTEXT
.
A coisa mais próxima que tivemos até agora foi essa CONTEXT_INFO
, que permite armazenar e compartilhar um único valor binário de até 128 bytes de comprimento, que é muito menos flexível do que o dicionário fornecido SESSION_CONTEXT
, que suporta vários valores de dados diferentes tipos.
SESSION_CONTEXT
é fácil de usar, basta chamar sp_set_session_context para armazenar o valor por uma chave desejada. Ao fazer isso, você fornece a chave e o valor, é claro, mas também pode definir o parâmetro read_only como true. Isso bloqueia o valor no contexto da sessão, para que não possa ser alterado pelo resto da vida útil da conexão. Assim, por exemplo, é fácil para um aplicativo cliente chamar esse procedimento armazenado para definir alguns valores de contexto da sessão logo após estabelecer a conexão com o banco de dados. Se o aplicativo definir o parâmetro read_only ao fazer isso, os procedimentos armazenados e outro código T-SQL que será executado no servidor poderão ler apenas o valor, eles não poderão alterar o que foi definido pelo aplicativo em execução no cliente.
Como teste, criei um gatilho de login do servidor que define algumas CONTEXT_SESSION
informações - uma delas SESSION_CONTEXT
foi definida como @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;
Entrei como um usuário completamente novo e consegui extrair as SESSION_CONTEXT
informações:
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
Eu até tentei alterar as informações de contexto 'read_only':
EXEC sp_set_session_context @key = N'CannotChange'
,@value = N'CannotChangeThisValue'
e recebeu um erro:
Msg 15664, Nível 16, Estado 1, Procedimento sp_set_session_context, Linha 1 [Linha 8 de Início do Lote] Não é possível definir a chave 'CannotChange' no contexto da sessão. A chave foi definida como somente leitura para esta sessão.
Uma observação importante sobre os gatilhos de login ( deste post )!
Um gatilho de logon pode efetivamente impedir conexões bem-sucedidas ao Mecanismo de Banco de Dados para todos os usuários, incluindo membros da função de servidor fixa sysadmin. Quando um gatilho de logon está impedindo conexões, os membros da função de servidor fixa sysadmin podem se conectar usando a conexão de administrador dedicada ou iniciando o Mecanismo de Banco de Dados no modo de configuração mínima (-f)
Uma desvantagem potencial é que isso preenche toda a instância do contexto da sessão (não por banco de dados). Neste ponto, as únicas opções em que consigo pensar são:
- Nomear seus
Session_Context
pares nome-valor prefixando-os com o nome do banco de dados de modo a não causar uma colisão com o mesmo nome do tipo em outro banco de dados. Isso não resolve o problema de pré-definir TODOS Session_Context
os valores de nome para todos os usuários.
- Quando o gatilho de login é acionado, você tem acesso a
EventData
(xml) que pode ser usado para extrair o usuário de login e, com base nisso, pode criar Session_Context
pares específicos de nome e valor.