재미,하지만 난 그냥 무슨 일이 있었이 함께 연주한다 :
create trigger dbo.Things_Log on dbo.Things after Delete, Insert, Update as
declare @Now as DateTimeOffset = SysDateTimeOffset();
-- Determine the action that fired the trigger.
declare @Action VarChar(6) =
case
when exists (select 42 from inserted) and exists (select 42 from deleted) then 'update'
when exists (select 42 from inserted) then 'insert'
when exists (select 42 from deleted) then 'delete'
else NULL end;
if @Action is NULL
return;
-- Assign a unique value to group the log rows for this trigger firing.
declare @TriggerId as Int;
update TriggerIds
set @TriggerId = TriggerId += 1;
-- Log the data.
if @Action in ('delete', 'update')
insert into ThingsLog
select @Action + '-deleted', @TriggerId, @Now, dbo.OriginalLoginName(), ThingId, ThingName
from deleted;
if @Action in ('insert', 'update')
insert into ThingsLog
select @Action + '-inserted', @TriggerId, @Now, dbo.OriginalLoginName(), ThingId, ThingName
from inserted;
go
-- Logging triggers should always fire last.
execute sp_settriggerorder @triggername = 'dbo.Things_Log', @order = 'Last', @stmttype = 'DELETE';
execute sp_settriggerorder @triggername = 'dbo.Things_Log', @order = 'Last', @stmttype = 'INSERT';
execute sp_settriggerorder @triggername = 'dbo.Things_Log', @order = 'Last', @stmttype = 'UPDATE';
go
컨텍스트 :
create function [dbo].[OriginalLoginName]()
returns NVarChar(128)
as
begin
-- Returns the original login used to create the current session: Domain\username or sqlusername.
-- This function is not affected by impersonation.
-- Requires granting execute access to [public] and represents a diminutive security hole.
declare @Result as NVarChar(128);
select @Result = original_login_name
from sys.dm_exec_sessions
where session_id = @@SPID;
return @Result;
end;
go
CREATE TABLE [dbo].[Things](
[ThingId] [int] IDENTITY(1,1) NOT NULL,
[ThingName] [varchar](16) NOT NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[ThingsLog](
[ThingsLogId] [int] IDENTITY(1,1) NOT NULL,
[Action] [varchar](16) NOT NULL,
[TriggerId] [int] NOT NULL,
[TriggerTime] [datetimeoffset](7) NOT NULL,
[OriginalLoginName] [nvarchar](128) NOT NULL,
[ThingId] [int] NOT NULL,
[ThingName] [varchar](16) NOT NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[TriggerIds](
[TriggerId] [int] NULL
) ON [PRIMARY]
GO
insert into dbo.TriggerIds (TriggerId) values (0);
로깅 트리거가 마지막 발사를 구성해야합니다. 이렇게하면 다른 트리거에 의해 롤백 될 수있는 로깅 동작이 금지됩니다. 보너스 포인트, 마지막 발사하도록 구성되지 않은 로깅 트리거를보고 할 수있는 쿼리를 위해 (당신이 트리거에 대한 일관된 명명 규칙, 예를 들어 TableName_Log을 가지고 가정) :
그것은 저장 프로 시저에 통합 할 수 있습니다
select PO.name as TableName, O.name as TriggerName, TE.type_desc,
case when O.name like PO.name + '_Log%' then 1 else 0 end as LoggingTrigger,
case when O.name like PO.name + '_Log%' and TE.is_last = 0 then 1 else 0 end as Misconfigured,
'' as [-], PO.type_desc as TableType, T.is_disabled, TE.is_first, TE.is_last, T.is_instead_of_trigger
from sys.objects as O inner join
sys.triggers as T on T.object_id = O.object_id inner join
sys.objects as PO on PO.object_id = T.parent_id inner join
sys.trigger_events as TE on TE.object_id = T.object_id
where
PO.type = 'U' and -- User table.
T.parent_class = 1 and -- Object or column trigger.
T.is_disabled = 0 and -- Is not disabled.
T.is_instead_of_trigger = 0 -- AFTER, not INSTEAD OF, trigger.
order by PO.name, O.name, TE.type_desc;
로깅 트리거의 실행 순서를 수정합니다.