我创建了一个处理更新的触发器,效果很好。但我正在努力研究如何处理插入。
这是我目前的触发器:
CREATE TRIGGER tr_PersonInCareSupportNeeds_History
ON PersonInCareSupportNeeds
FOR UPDATE
AS
BEGIN
INSERT INTO [dbo].[PersonInCareSupportNeeds_History]
([PersonInCareSupportNeedsID], [EventDate], [EventUser], [ChangedColumn], [PreviousValue], [NewValue])
SELECT i.[PersonInCareSupportNeedsID], GETDATE(), i.[LastUpdateUser], 'StartDate', CAST(d.[StartDate] AS VARCHAR), CAST(i.[StartDate] AS VARCHAR)
FROM PersonInCareSupportNeeds I INNER JOIN Deleted D
ON d.PersonInCareSupportNeedsID = I.PersonInCareSupportNeedsID
WHERE d.[StartDate] <> i.[StartDate]
UNION
-- new values
SELECT i.[PersonInCareSupportNeedsID], GETDATE(), i.[LastUpdateUser], 'EndDate', CAST(d.[EndDate] AS VARCHAR), CAST(i.[EndDate] AS VARCHAR)
FROM PersonInCareSupportNeeds I INNER JOIN DELETED D
ON d.PersonInCareSupportNeedsID = I.PersonInCareSupportNeedsID
WHERE d.[EndDate] <> i.[EndDate]
END
如何更改此项以处理INSERTS。我还会有一个专栏来处理动作类型'Updated'或'Inserted'。
答案 0 :(得分:0)
好笑,但我碰巧正在玩这个:
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;
它可以合并到一个存储过程中,以纠正记录触发器的触发顺序。