Как получить текст процедуры перед изменением с триггера DDL
-
19-09-2019 - |
Вопрос
Я создаю триггер, чтобы отслеживать, как был текст процедуры ALTER
редакция
Внутри триггера DDL базы данных можно получить доступ к текущей процедуре через текст через /EVENT_INSTANCE/TSQLCommand
.
Даже после расследования EVENTDATA()
, он не содержал значений для предыдущего определения процедуры до ALTER
.
Есть ли способ получить предыдущий текст, например, как можно получить доступ к удаленным значениям в DML -триггерах, используя DELETED
стол?
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
Решение
Триггер работает после того, как было внесено изменение, поэтому, насколько я могу судить, нет доступа к значениям «до». EventData () определено, и нет никаких положений для «предыдущего». В результате вам придется просто записать текущее значение в журнале. Однако, если вы предварительно заполните свой журнал с помощью этой команды:
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'
Вы можете использовать свой триггер и при этом иметь полную картину всех изменений. Ваш журнал будет иметь все предыдущие версии, а также текущая версия каждой процедуры. Вы можете использовать мою версию триггера (см. Ниже), где у вас будет доступ к некоторым другим столбцам из Sys.objects и Sys.sql_Modules, например:
uses_ansi_nulls
uses_quoted_identifier
is_schema_bound
null_on_null_input
principal_id
что может быть удобно для регистрации. Альтернативная версия:
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