Sql-Server-2008

SQL Server:更新觸發器在插入觸發器之前觸發

  • July 23, 2018

我有一個帶有 SQL Server 託管數據庫的應用程序。我無權訪問應用程式碼,但我可以完全訪問數據庫。我已將自己的自定義審核添加到表中以幫助調試。

我正在使用after觸發器。以下是我的觸發器的簡化版本。

問題:我看到update相應審計記錄之前的insert審計記錄。這怎麼可能?差異只有幾毫秒,對我目前的目的來說並不重要,但我可以想像程序邏輯依賴於正確的年表的更糟糕的場景。

我知道在同類(全部insert或全部update)觸發器之間控制觸發器執行順序的方法。我可以對異構觸發器執行順序做出哪些假設?

create trigger dbo.MyTrigger_i on dbo.theTable
after insert
as
begin
   set nocount on
   declare @Date datetime, @User sysname
   set @Date = GETDATE()
   set @User = SUSER_SNAME()
   insert into MyAudit (RowID, [Date], UserName, Comment)
           select i.ID, @Date, @User, 'Insert'
           from 
               inserted as i
end
go

create trigger dbo.MyTrigger_u on dbo.theTable
after update
as
begin
   set nocount on
   declare @Date datetime, @User sysname
   set @Date = GETDATE()
   set @User = SUSER_SNAME()
   insert into MyAudit (RowID, [Date], UserName, Comment)
           select 
               i.ID, @Date, @User, 'Update'
           from
               inserted as i
               inner join deleted as d
                   on i.ID = d.ID
end
go

考慮到a)觸發器自然是觸發觸發器的DML語句的事務的一部分,並且b)在行存在之前不能在行上發生更新,實際的更新不可能在實際的插入之前出現. 因此,正在發生其他事情。

需要考慮的事項:

  1. 問題中顯示的觸發器定義是實際的和目前的定義嗎?是否有可能Comment在觸發器中切換“插入”和“更新”的值,以便插入觸發器具有“更新”的註釋,反之亦然?
  2. 觸發器是否有可能UPDATE以某種方式定義為AFTER INSERT, UPDATE?如果是這樣,一個INSERT操作將觸發兩個觸發器,使其看起來既是一個INSERT又是一個UPDATE發生,而實際上沒有UPDATE操作(這也可以解釋為什麼審計條目的時間僅相隔幾毫秒)。
  3. 您確定“相應”記錄的查詢是否可能存在缺陷並且結果具有誤導性?

我剛剛發生了這種確切的情況並弄清楚發生了什麼(至少對於我的情況)。我的桌子上有一個舊的第三個觸發器,它是這樣的:

CREATE TRIGGER [dbo].[MyTrigger_fi] ON [dbo].[theTable] 
FOR INSERT
AS
UPDATE theTable
SET ReportingDate = ot.ReportingDate
FROM Inserted i
JOIN theTable tb ON tb.ID = i.ID
JOIN OtherTable ot on ot.ID = tb.OtherTableID

FOR INSERT 發生在我的 AFTER INSERT 之前,執行更新,然後觸發了我的 AFTER UPDATE 觸發器。最終結果是在每次插入時在我的插入消息之前記錄一條更新消息。一切都是這樣的:

Record Inserted
   FOR INSERT trigger fires
       Record is Updated
           AFTER UPDATE trigger fires
               Update Event is recorded
   AFTER INSERT trigger fires
       Insert Event is recorded

引用自:https://dba.stackexchange.com/questions/95741