2013-07-29 49 views
0

我创建了一个处理更新的触发器,并且运行良好。但我正在努力研究如何处理插入。更新触发器正在工作但无法执行插入

这是我目前的触发:

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 

我怎样才能改变这种处理刀片以及。我也会有一个专栏来处理动作类型'更新'或'插入'。

回答

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; 

它可以在存储过程中被合并这可以纠正记录触发器的触发顺序。