Utilizzo della funzione EVENTDATA
La funzione EVENTDATA consente di acquisire le informazioni relative a un evento che attiva un trigger DDL. La funzione restituisce un valore xml
. XML Schema include le informazioni relative a:
Ora dell'evento.
ID di processo di sistema (SPID) della connessione nel momento in cui è stato eseguito il trigger.
Tipo di evento che ha attivato il trigger.
A seconda del tipo di evento, lo schema include quindi informazioni aggiuntive, ad esempio il database in cui si è verificato l'evento, l'oggetto su cui si è verificato l'evento e l'istruzione Transact-SQL dell'evento. Per altre informazioni, vedere Trigger DDL.
Ad esempio, il trigger DDL seguente viene creato nel database di esempio AdventureWorks2012 :
CREATE TRIGGER safety
ON DATABASE
FOR CREATE_TABLE
AS
PRINT 'CREATE TABLE Issued.'
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
RAISERROR ('New tables cannot be created in this database.', 16, 1)
ROLLBACK
;
Viene quindi eseguita l'istruzione CREATE TABLE
seguente:
CREATE TABLE NewTable (Column1 int);
L'istruzione EVENTDATA()
nel trigger DDL acquisisce il testo dell'istruzione CREATE TABLE
, che non è consentita. Ciò viene ottenuto usando un'istruzione XQuery sui xml
dati generati da EVENTDATA e recuperando l'elemento <CommandText> . Per altre informazioni, vedere Informazioni di riferimento sul linguaggio XQuery (SQL Server).
Attenzione
EVENTDATA acquisisce i dati degli eventi CREATE_SCHEMA e la <schema_element> della definizione CREATE SCHEMA corrispondente, se presente. EVENTDATA riconosce inoltre la <definizione di schema_element> come evento separato. Pertanto, un trigger DDL creato in un evento CREATE_SCHEMA e un evento rappresentato dalla <schema_element> della definizione CREATE SCHEMA, può restituire due volte gli stessi dati dell'evento, ad esempio i TSQLCommand
dati. Si consideri ad esempio la creazione di un trigger DDL su entrambi gli eventi CREATE_SCHEMA e CREATE_TABLE e la successiva esecuzione del batch seguente:
CREATE SCHEMA s
CREATE TABLE t1 (col1 int)
È importante tenere presente che, se l'applicazione recupera i dati TSQLCommand
dell'evento CREATE_TABLE, è possibile che i dati vengano visualizzati due volte: alla generazione dell'evento CREATE_SCHEMA e di nuovo alla generazione dell'evento CREATE_TABLE. Evitare di creare trigger DDL sia negli eventi di CREATE_SCHEMA che nei <testi schema_element> di eventuali definizioni CREATE SCHEMA corrispondenti o compilare la logica nell'applicazione in modo che lo stesso evento non venga elaborato due volte.
Eventi ALTER TABLE e ALTER DATABASE
I dati degli eventi ALTER_TABLE e ALTER_DATABASE includono anche i nomi e i tipi degli altri oggetti interessati dall'istruzione DDL e dall'azione eseguita su questi oggetti. I dati degli eventi ALTER_TABLE includono i nomi delle colonne, dei vincoli o dei trigger interessati dall'istruzione ALTER TABLE e dall'azione (creazione, modifica, rimozione, abilitazione o disabilitazione) eseguita su tali oggetti. I dati degli eventi ALTER_DATABASE includono i nomi di tutti i file o i filegroup interessati dall'istruzione ALTER DATABASE e dall'azione (creazione, modifica o rimozione) eseguita su tali oggetti.
Creare, ad esempio, il trigger DDL seguente nel database di esempio AdventureWorks:
CREATE TRIGGER ColumnChanges
ON DATABASE
FOR ALTER_TABLE
AS
-- Detect whether a column was created/altered/dropped.
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)')
RAISERROR ('Table schema cannot be modified in this database.', 16, 1);
ROLLBACK;
Eseguire quindi l'istruzione ALTER TABLE seguente che viola un vincolo:
ALTER TABLE Person.Address ALTER COLUMN ModifiedDate date;
L'istruzione EVENTDATA() nel trigger DDL acquisisce il testo dell'istruzione ALTER TABLE
, che non è consentita.
Esempio
È possibile utilizzare la funzione EVENTDATA per creazione di un log eventi. Nell'esempio seguente viene creata una tabella per l'archiviazione delle informazioni relative agli eventi. Viene quindi creato nel database corrente un trigger DDL che popola la tabella con le informazioni seguenti ogni volta che viene generato un evento DDL a livello del database:
Ora dell'evento (tramite la funzione GETDATE).
Utente del database che ha attivato la sessione durante la quale è stato generato l'evento (tramite la funzione CURRENT_USER).
Tipo di evento.
Istruzione Transact-SQL che include l'evento.
Anche in questo caso, per l'acquisizione degli ultimi due elementi viene utilizzato XQuery per i dati xml
generati da EVENTDATA.
USE AdventureWorks2012;
GO
CREATE TABLE ddl_log (PostTime datetime, DB_User nvarchar(100), Event nvarchar(100), TSQL nvarchar(2000));
GO
CREATE TRIGGER log
ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS
AS
DECLARE @data XML
SET @data = EVENTDATA()
INSERT ddl_log
(PostTime, DB_User, Event, TSQL)
VALUES
(GETDATE(),
CONVERT(nvarchar(100), CURRENT_USER),
@data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)'),
@data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(2000)') ) ;
GO
--Test the trigger
CREATE TABLE TestTable (a int)
DROP TABLE TestTable ;
GO
SELECT * FROM ddl_log ;
GO
Nota
Per la restituzione di dati sugli eventi è consigliabile utilizzare il metodo XQuery value()
anziché il metodo query()
. Il metodo query()
restituisce output XML con le istanze CR/LF (ritorno a capo/avanzamento riga) trasformate con il carattere di escape e commerciale (&), mentre il metodo value()
rende le istanze CR/LF invisibili nell'output.
Un esempio di trigger DDL simile viene fornito con il database di esempio AdventureWorks2012 . Per ottenere l'esempio, individuare la cartella Trigger di database usando SQL Server Management Studio. Questa cartella si trova nella cartella Programmabilità del database AdventureWorks2012. Fare clic con il pulsante destro del mouse su ddlDatabaseTriggerLog e scegliere Crea script per trigger database. Per impostazione predefinita, il trigger DDL ddlDatabaseTriggerLog è disabilitato.