Como identificar a query que disparou uma trigger de DML numa tabela? Li essa dúvida num grupo do Telegram e resolvi escrever um artigo sobre isso.
Introdução
Como vocês sabem, existem várias soluções para se implementar um log de auditoria com as alterações de dados em uma determinada tabela:
- SQL Server – Como monitorar e auditar alterações de dados em tabelas utilizando Change Data Capture (CDC)
- SQL Server 2016 – Como “viajar no tempo” utilizando o recurso Temporal Tables
- SQL Server – Como criar um histórico de alterações de dados para suas tabelas (logs para auditoria)
- Auditoria no SQL Server (Server Audit)
Uma das soluções mais utilizadas para isso, é a utilização de triggers de DML (Saiba como implementar isso clicando aqui)
Em alguns cenários, é importante identificar qual a consulta que acabou disparando a trigger para talvez identificar a origem dos dados que estão sendo inseridos a partir do SQL. E é isso que aprenderemos como fazer nesse post.
Caso você queira mais detalhes da origem desse comando e identificar toda a cadeia de execução da trigger, sugiro a leitura do artigo SQL Server – Como identificar e monitorar a execução de triggers.
Criando a base de testes
Para a demonstração dos códigos desse artigo, vou compartilhar com vocês o script que utilizei para montar essa tabela e a trigger utilizada para auditar as alterações. Vou utilizar o mesmo exemplo do artigo SQL Server – Como criar um histórico de alterações de dados para suas tabelas (logs para auditoria).
Criação das tabelas
Clique aqui para visualizar código da criação das tabelas
Criação da trigger:
Clique aqui para visualizar o código da trigger
Faço algumas alterações na tabela original:
INSERT INTO dbo.Cliente
VALUES ('Bartolomeu', '1975-05-28', 6158.74)
UPDATE dbo.Cliente
SET Salario = Salario * 1.5
WHERE Nome = 'Bartolomeu'
DELETE FROM dbo.Cliente
WHERE Nome = 'André'
UPDATE dbo.Cliente
SET Salario = Salario * 1.1
WHERE Id_Cliente = 2
UPDATE dbo.Cliente
SET Salario = 10, Nome = 'Judas Iscariodes', Data_Nascimento = '06/06/2066'
WHERE Id_Cliente = 1
E podemos ver que a auditoria está funcionando conforme o esperado:

Como identificar a query que disparou a trigger
Agora descobriremos como identificar a query que disparou a trigger.
Para isso, vamos alterar a trigger e incluir o comando INPUTBUFFER para capturar a query e armazenar essa informação na tabela de log.
A sintaxe de utilização do comando é assim:
DECLARE @SqlQuery VARCHAR(MAX)
DECLARE @TableSqlQuery TABLE (
EventType NVARCHAR(30),
[Parameters] INT,
EventInfo NVARCHAR(MAX)
)
INSERT INTO @TableSqlQuery
EXEC('DBCC INPUTBUFFER(@@SPID)')
SET @SqlQuery = (SELECT TOP(1) EventInfo FROM @TableSqlQuery)
Adicionaremos o campo que armazenará a query na tabela:
ALTER TABLE dbo.Cliente_Log ADD Ds_Query VARCHAR(MAX)
E agora alteramos a trigger:
Clique aqui para visualizar código da trigger
E vamos testar novamente executando o comando abaixo:
INSERT INTO dbo.Cliente
VALUES('Dirceu', '1987-05-28', 0)
INSERT INTO dbo.Cliente
SELECT
'Resende' AS Nome,
'1987-05-28' AS Dt_Nascimento,
9999 AS Vl_Salario
Como as 2 instruções SQL foram executadas juntas, no mesmo batch, o comando INPUTBUFFER capturou os 2 comandos de uma vez. Se eu tentar executar novamente, mas utilizando um GO para separar os blocos ou mesmo, executando separadamente, podemos observar que a trigger agora vai identificar corretamente os comandos de cada instrução:
INSERT INTO dbo.Cliente
VALUES('Dirceu - Teste 2', '1987-05-28', 0)
GO
INSERT INTO dbo.Cliente
SELECT
'Resende - Teste 2' AS Nome,
'1987-05-28' AS Dt_Nascimento,
9999 AS Vl_Salario
GO
E se tiver outra trigger, em outra tabela, que está alterando a tabela Cliente e você não está conseguindo identificar de onde vem esse comando?
Primeiro, criaremos uma tabela com dados de funcionários:
IF (OBJECT_ID('dbo.Funcionario') IS NOT NULL) DROP TABLE dbo.Funcionario
GO
CREATE TABLE dbo.Funcionario (
Id_Funcionario INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
Nome VARCHAR(100)
)
GO
INSERT INTO dbo.Funcionario
(
Nome
)
VALUES
( 'Dirceu' ), ('Resende')
Agora criarei uma trigger nessa nova tabela que atualiza a tabela Cliente caso o cliente e o funcionário tenham o mesmo nome:
CREATE TRIGGER trgFuncionario ON dbo.Funcionario -- Tabela que a trigger será associada
AFTER UPDATE AS
BEGIN
SET NOCOUNT ON
UPDATE A
SET A.Nome = B.Nome
FROM dbo.Cliente A
JOIN Inserted B ON A.Nome = B.Nome
END
GO
Ao executar um simples comando de UPDATE, veremos que a trigger foi disparada nas duas tabelas
UPDATE dbo.Funcionario
SET Nome = 'Dirceu Resende'
WHERE Id_Funcionario = 1
Que legal! Mesmo o comando vindo de outra trigger, foi possível identificar a origem dessa alteração.
Mas e se você quiser mais detalhes da origem desse comando e identificar toda a cadeia de execução da trigger? Bom, neste caso, sugiro a leitura do artigo SQL Server – Como identificar e monitorar a execução de triggers.
Espero que vocês tenham gostado desse artigo e até a próxima 🙂
Abraços!



Comentários (0)
Carregando comentários…