Como obter o texto do procedimento antes de alterar do ddl gatilho
-
19-09-2019 - |
Pergunta
Estou criando um gatilho para rastrear como o texto do procedimento foi ALTER
ed.
Dentro de um gatilho DDL de banco de dados, é possível acessar o texto do procedimento atual por meio /EVENT_INSTANCE/TSQLCommand
.
Mesmo depois de investigar EVENTDATA()
, não continha valores para a definição anterior de procedimento antes ALTER
.
Existe uma maneira de recuperar o texto anterior, como é possível acessar valores excluídos em gatilhos de DML usando DELETED
tabela?
create trigger trgDDLAuditQuery
on database
for alter_procedure
as
begin
set nocount on;
declare @data xml
set @data = EVENTDATA()
insert dbo.tblQueryAudit(ObjectName, TSQLCommand)
select @data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(256)'),
--; Only gets currently changed procedure text, not previous one
@data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)')
end
GO
Solução
O gatilho funciona após a alteração, tanto quanto eu sei, não há acesso aos valores "antes". O EventData () é definido e não há provisão para "anterior". Como resultado, você precisará apenas registrar o valor atual no log. No entanto, se você preparar seu log com este comando:
INSERT INTO dbo.tblQueryAudit
(ObjectName, TSQLCommand)
SELECT
o.Name,m.definition
FROM sys.objects o
INNER JOIN sys.sql_modules m ON o.object_id=m.object_id
WHERE type='P'
Você pode usar seu gatilho e ainda ter uma imagem completa de todas as alterações. Seu log teria todas as versões anteriores, bem como a versão atual de cada procedimento. Você pode usar minha versão do gatilho (veja abaixo), onde teria acesso a algumas das outras colunas do Sys.Objects e Sys.SQL_Modules, como:
uses_ansi_nulls
uses_quoted_identifier
is_schema_bound
null_on_null_input
principal_id
o que pode ser útil para registrar também. versão alternativa:
CREATE trigger trgDDLAuditQuery
on database
for alter_procedure
as
begin
set nocount on;
DECLARE @EventData xml
SET @EventData=EVENTDATA()
INSERT INTO dbo.tblQueryAudit
(ObjectName, TSQLCommand) --hope you have datetime column that defaults to GETDATE()
SELECT
o.Name,m.definition
FROM sys.objects o
INNER JOIN sys.sql_modules m ON o.object_id=m.object_id
WHERE o.Name=@EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(max)')
--modify as necessary AND type='P'
end
GO