如果 @@TRANCOUNT 的值在預存程序完成時與過程執行時不同,則會產生一個 266 資訊類錯誤。該錯誤不是由觸發器中同一個條件產生的。
當調用預存程序時,如果 @@TRANCOUNT 為 1 或更大,並且該過程執行 ROLLBACK TRANSACTION 或 ROLLBACK WORK 語句,則會產生 266 號錯誤。這是因為 ROLLBACK 復原所有未完成的事務,並將 @@TRANCOUNT 減到 0,該值比調用過程時要小。
如果在觸發器中發出 ROLLBACK TRANSACTION:
- 對當前事務中的那一點所做的所有資料修改都將復原,包括觸發器所做的修改。
- 觸發器繼續執行 ROLLBACK 語句之後的所有其餘語句。如果這些語句中的任意語句修改資料,則不復原這些修改。執行其餘的語句不會激發嵌套觸發器。
- 在批處理中,所有位於激發觸發器的語句之後的語句都不被執行。
- 觸發器中的 ROLLBACK 關閉並釋放所有在包含激發觸發器的語句的批處理中聲明和開啟的遊標。這其中包括了在激發觸發器的批處理所調用的預存程序中聲明和開啟的遊標。在激發觸發器的批處理之前的批處理中所聲明的遊標將只是關閉,但是在以下條件下,STATIC 或 INSENSITIVE 遊標不關閉:
- CURSOR_CLOSE_ON_COMMIT 設定為OFF。
- 靜態資料指標要麼是同步遊標,要麼是完全填充的非同步遊標。
當執行觸發器時,觸發器的操作總是好像有一個未完成的事務在起作用。如果激發觸發器的語句是在隱性或明確交易中,則肯定會這樣。在自動認可模式下,也是如此。當語句開始以自動認可模式執行時,如果遇到錯誤,則會有隱含的 BEGIN TRANSACTION 語句允許恢複該語句產生的所有修改。該隱含的事務對批處理中的其它語句沒有影響,因為當陳述式完成時,該事務要麼提交,要麼復原。但是,當調用觸發器時,該隱含的事務將仍然有效。
這意味著,只要觸發器中發出 BEGIN TRANSACTION 語句,則實際上就開始了一個嵌套事務。因為當復原嵌套事務時,嵌套的 BEGIN TRANSACTION 語句將被忽略,觸發器中發出的 ROLLBACK TRANSACTION 總是復原過去該觸發器本身發出的所有 BEGIN TRANSACTION 語句。ROLLBACK 復原到最外部的 BEGIN TRANSACTION。
若要在觸發器中進行部分復原,則即使總是以自動認可模式進行調用,也必須使用 SAVE TRANSACTION 語句。以下的觸發器闡明了這一點:
CREATE TRIGGER TestTrig ON TestTab FOR UPDATE ASSAVE TRANSACTION MyNameINSERT INTO TestAuditSELECT * FROM insertedIF (@@error <> 0)BEGINROLLBACK TRANSACTION MyNameEND
這也影響觸發器中 BEGIN TRANSACTION 語句後面的COMMIT TRANSACTION 語句。因為 BEGIN TRANSACTION 啟動一個嵌套事務,而隨後的 COMMIT 語句只應用於該嵌套事務。如果在 COMMIT 之後執行 ROLLBACK TRANSACTION 語句,那麼 ROLLBACK 將一直復原到最外部的 BEGIN TRANSACTION。以下的觸發器闡明了這一點:
CREATE TRIGGER TestTrig ON TestTab FOR UPDATE ASBEGIN TRANSACTIONINSERT INTO TrigTargetSELECT * FROM insertedCOMMIT TRANSACTIONROLLBACK TRANSACTION
此觸發器絕對不會在 TrigTarget 表中插入。BEGIN TRANSACTION 總是啟動一個嵌套事務。COMMIT TRANSACTION 只提交嵌套事務,而下面的 ROLLBACK TRANSACTION 則一直復原到最外部的 BEGIN TRANSACTION。