Sql-Server

插入後觸發阻止插入

  • January 10, 2018

我有兩個必須具有相似資訊的表,其中一個可以被認為是另一個的基表,所以為了在兩個表中都有資訊,我創建了這個觸發器:

ALTER TRIGGER [dbo].[TR_INSERTED_READER_LOG] 
ON [dbo].[TBL_READER_LOG]
AFTER INSERT
AS
IF EXISTS(SELECT * FROM INSERTED WHERE REL_ENROLLNUMBER < 9999999)
BEGIN
   SET LANGUAGE us_english
   DECLARE @DEV_NID INT
   DECLARE @DATE DATETIME
   DECLARE @USE_NID INT
   DECLARE @REL_MODE INT 
   SELECT @DEV_NID = DEV_NID, 
          @DATE = LOG_DATE, 
          @USE_NID = REL_ENROLLNUMBER, 
          @REL_MODE = REL_MODE 
   FROM TBL_DEVICE 
   INNER JOIN TBL_READER_LOG ON DEV_ORIGINAL_NID = RDR_NID WHERE DEV_TYPE = 1
   INSERT INTO TBL_USER_LOGS (DEV_NID, LOG_DATE, USE_NID, LOG_MODE) VALUES (@DEV_NID, @DATE, @USE_NID, @REL_MODE)
END

它工作正常,但是當觸發器中的插入語句有錯誤(如 FK 違規)時,會阻止可以插入第一個表中的數據。

我在微軟的文件中搜尋並說當所有指令都已經完成時After Insert執行,為什麼阻止插入?Trigger

  1. 觸發器是原始事務的一部分。僅僅因為它發生在原始插入之後並不意味著在發生錯誤時一切都不會回滾。回滾不只是回滾最後執行的東西。舉個例子:
BEGIN TRANSACTION;
INSERT dbo.table1 ...;
INSERT dbo.table2 ...;
ROLLBACK TRANSACTION;

您肯定不希望回滾只會影響第二次插入嗎? 2. 您可能會考慮使用 TRY/CATCH 或 INSTEAD OF 觸發器,這將允許您處理其他內容而不會遇到錯誤。或者只是先檢查 3. 您使用聲明一堆變數,從連接中分配它們,然後插入似乎既低效又存在問題。如果多於一行與聯接匹配,會發生什麼情況?你知道如果你有一個多行操作,觸發器只會觸發一次,所以你最終只會插入一個任意行,對吧?為什麼不:

INSERT dbo.TBL_USER_LOGS(DEV_NID, LOG_DATE, USE_NID, LOG_MODE)
 SELECT DEV_NID, LOG_DATE, REL_ENROLLNUMBER, REL_MODE -- table prefixes?
FROM dbo.TBL_DEVICE -- always use dbo prefix! 
INNER JOIN dbo.TBL_READER_LOG 
ON DEV_ORIGINAL_NID = RDR_NID -- which table do these columns come from?
WHERE DEV_TYPE = 1; -- which table does this column come from?

順便說一句,我注意到您的查詢似乎沒有考慮inserted偽表。插入不應該與實際受觸發器影響的行有關嗎?

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