預存程序和觸發程序中的回復與認可
可能可以在預存程序或觸發程序內部執行 ROLLBACK TRANSACTION 或 COMMIT TRANSACTION Transact-SQL 陳述式,但這樣做可能會產生錯誤。
在預存程序中
如果 @@TRANCOUNT 在預存程序完成時的值與執行程序時的值不同,便會產生參考用錯誤 (266)。有兩種情形會產生這個錯誤:
- 使用 @@TRANCOUNT 為 1 或更大的值呼叫預存程序,且預存程序執行 ROLLBACK TRANSACTION 陳述式。完成預存程序時,@@TRANCOUNT 會減為 0 並產生錯誤 266。
- 使用 @@TRANCOUNT 為 1 或更大的值呼叫預存程序,且預存程序執行 COMMIT TRANSACTION 陳述式。完成預存程序時,@@TRANCOUNT 會減 1 並產生錯誤 266。不過,如果先執行 COMMIT TRANSACTION 然後再執行 BEGIN TRANSACTION,則不會產生錯誤。
在觸發程序中
觸發程序的運作就像是在執行觸發程序時,會受到尚未處理完畢的交易影響一樣。引發觸發程序的陳述式如果是在隱含交易或外顯交易中,則這種情形永遠為 true。
當陳述式開始執行於自動認可模式時,隱含的 BEGIN TRANSACTION 便允許陳述式在遇到錯誤時,將自己產生的一切修改復原。這個隱含的交易不會影響到批次中的其他陳述式,因為它會在陳述式完成時被認可或復原。但是,當呼叫某個觸發程序時,此隱含的交易仍然有影響。
執行觸發程序時,會啟動隱含交易。如果觸發程序完成執行且 @@TRANCOUNT = 0 並發生錯誤 3609,則會終止批次。基於這個原因,在觸發程序內建議避免使用 ROLLBACK TRANSACTION (會將 @@TRANCOUNT 重設為 0) 和 COMMIT TRANSACTION (會將 @@TRANCOUNT 減為 0)。在回復之後發出 BEGIN TRANSACTION 陳述式將會停止引發錯誤,不過這樣卻會造成應用程式邏輯的問題。
務必瞭解在觸發程序中發出的 BEGIN TRANSACTION 陳述式,實際上會開始巢狀交易。在此狀況中,執行 COMMIT TRANSACTION 陳述式只會套用至巢狀交易。由於在回復巢狀交易時會忽略巢狀 BEGIN TRANSACTION 陳述式,因此在觸發程序中執行的 ROLLBACK TRANSACTION,會略過觸發程序本身所發出的 BEGIN TRANSACTION 陳述式而回復。ROLLBACK 會回復到最外部的交易並將 @@TRANCOUNT 設為 0。
在觸發程序中使用 ROLLBACK TRANSACTION 時,請注意下列行為:
- 在目前交易中進行至該點的所有資料修改都會復原,包括觸發程序所做的修改。
- 觸發程序會在 ROLLBACK 陳述式之後,繼續執行任何其餘陳述式。如果有任何這些陳述式修改資料,不會回復這些修改。
- 觸發程序中的 ROLLBACK 關閉,並把包含引發觸發程序之陳述式的批次中宣告及開啟的資料指標全部取消配置。其中包括宣告及開啟於由引發觸發程序之批次所呼叫的預存程序中的資料指標。在引發觸發程序的批次前宣告的資料指標只能是已關閉。不過在下列情況中,STATIC 或 INSENSITIVE 資料指標可以保持開啟:
- CURSOR_CLOSE_ON_COMMIT 設定為 OFF。
- 靜態資料指標為同步或為完整擴展的非同步資料指標。
不使用 ROLLBACK TRANSACTION 而使用 SAVE TRANSACTION 陳述式,可以在觸發程序中執行部份回復。
請參閱
概念
其他資源
@@TRANCOUNT (Transact-SQL)
ROLLBACK TRANSACTION (Transact-SQL)
ROLLBACK WORK (Transact-SQL)
SAVE TRANSACTION (Transact-SQL)