Dal momento che apparentemente stai usando SQL Server 2016, vorrei buttare via un'altra opzione ' possibile ' - SESSION_CONTEXT
.
L'articolo di Leonard Lobel, Condivisione dello stato in SQL Server 2016 conSESSION_CONTEXT
alcune ottime informazioni su questa nuova funzionalità in SQL Server 2016.
Riassumendo alcuni punti chiave:
Se hai mai desiderato condividere lo stato della sessione attraverso tutte le procedure e i batch archiviati per tutta la durata di una connessione al database, ti piacerà SESSION_CONTEXT
. Quando ci si connette a SQL Server 2016, si ottiene un dizionario con stato, o ciò che viene spesso indicato come un sacchetto di stato, un luogo in cui è possibile memorizzare valori, come stringhe e numeri, e quindi recuperarlo con una chiave assegnata. Nel caso di SESSION_CONTEXT
, la chiave è qualsiasi stringa e il valore è sql_variant, il che significa che può ospitare una varietà di tipi.
Una volta archiviato qualcosa SESSION_CONTEXT
, rimane lì fino alla chiusura della connessione. Non è memorizzato in alcuna tabella nel database, rimane solo nella memoria finché la connessione rimane attiva. E qualsiasi codice T-SQL in esecuzione all'interno di stored procedure, trigger, funzioni o altro, può condividere qualsiasi cosa tu faccia
SESSION_CONTEXT
.
La cosa più simile a questa che abbiamo avuto finora è stata CONTEXT_INFO
, che consente di archiviare e condividere un singolo valore binario lungo fino a 128 byte, che è molto meno flessibile del dizionario che si ottiene SESSION_CONTEXT
, che supporta più valori di dati diversi tipi.
SESSION_CONTEXT
è facile da usare, basta chiamare sp_set_session_context per memorizzare il valore con una chiave desiderata. Quando lo fai, fornisci la chiave e il valore ovviamente, ma puoi anche impostare il parametro read_only su true. Questo blocca il valore nel contesto della sessione, in modo che non possa essere modificato per il resto della durata della connessione. Quindi, ad esempio, è facile per un'applicazione client chiamare questa procedura memorizzata per impostare alcuni valori di contesto di sessione subito dopo aver stabilito la connessione al database. Se l'applicazione imposta il parametro read_only quando lo fa, le procedure memorizzate e l'altro codice T-SQL che viene quindi eseguito sul server possono solo leggere il valore, non possono cambiare ciò che è stato impostato dall'applicazione in esecuzione sul client.
Come test, ho creato un trigger di accesso al server che imposta alcune CONTEXT_SESSION
informazioni - una delle quali SESSION_CONTEXT
era impostata su @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;
Ho effettuato l'accesso come utente completamente nuovo ed è stato in grado di estrarre le SESSION_CONTEXT
informazioni:
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
Ho anche tentato di modificare le informazioni di contesto "read_only":
EXEC sp_set_session_context @key = N'CannotChange'
,@value = N'CannotChangeThisValue'
e ha ricevuto un errore:
Messaggio 15664, livello 16, stato 1, procedura sp_set_session_context, riga 1 [riga iniziale batch 8] Impossibile impostare la chiave "CannotChange" nel contesto della sessione. La chiave è stata impostata come read_only per questa sessione.
Una nota importante sui trigger di accesso ( da questo post )!
Un trigger di accesso può impedire efficacemente connessioni riuscite al Motore di database per tutti gli utenti, inclusi i membri del ruolo predefinito del server sysadmin. Quando un trigger di accesso impedisce le connessioni, i membri del ruolo predefinito del server sysadmin possono connettersi utilizzando la connessione di amministratore dedicata o avviando il Motore di database in modalità di configurazione minima (-f)
Un potenziale svantaggio è che questo riempie l'istanza del contesto della sessione (non per database). A questo punto, le uniche opzioni che mi vengono in mente sono:
- Assegna un
Session_Context
nome alle coppie nome-valore aggiungendole al prefisso con il nome del database in modo da non provocare una collisione per lo stesso nome di tipo in un altro database. Questo non risolve il problema di pre-definire TUTTI Session_Context
i valori dei nomi per tutti gli utenti.
- Quando viene attivato il trigger di accesso, si ha accesso a
EventData
(xml) che è possibile utilizzare per estrarre l'utente di accesso e in base a ciò, è possibile creare Session_Context
coppie nome-valore specifiche .