2013-07-29 4 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 

가 어떻게뿐만 아니라 삽입을 처리하려면이 옵션을 변경할 수 있습니다. 나는 또한 액션 유형 'Updated'또는 'Inserted'를 처리 할 칼럼을 가질 것이다.

답변

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; 

로깅 트리거의 실행 순서를 수정합니다.

관련 문제