2013-07-29 78 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; 

它可以在存儲過程中被合併這可以糾正記錄觸發器的觸發順序。