儲存過程出錯時,為什麼要送出部分事務?
我有一個儲存過程,它首先聲明一些變數,然後包含
begin tran;
在此之後,它對提供的參數執行一些驗證(並且每次提供的參數驗證失敗時都會增加一個錯誤計數)。如果沒有錯誤計數,則繼續執行 7 次插入。在此之後,它有commit tran;
最近我在列表中添加了第 8 個插入。隱式類型轉換意味著如果插入某些插入的數據將被截斷。這向 SSMS 螢幕拋出了一個錯誤,但我發現前 7 個插入已送出,而第 8 個顯然沒有完成。
我很感激我可以包含一個
try ... catch
塊來處理錯誤,但是如果一個顯式begin tran;
不能使整個工作塊自治到commit
,那麼有什麼意義呢?我錯過了什麼?我知道我也許可以將我的程序呼叫包含在該級別的事務中 - 但是有人可以解釋發生了什麼以及為什麼
begin tran
當包含在程序主體中時似乎不受尊重?如果呼叫該過程開始一個隱式事務,那麼 proc 中的錯誤步驟是否不應該回滾由 proc 影響的所有更改 - 即使沒有明確包括begin tran
在 proc 主體中?
事務不會在錯誤時自動回滾——這不是它們的設計目的。它們旨在使您能夠回滾。但是,您仍然需要做一些事情來實現這一點。
正如您所提到的,您可以通過 實現這一點
TRY...CATCH
,這使您可以最大程度地控制是否以及如何回滾。聽起來您期待 的行為
SET XACT_ABORT ON
,您可以在儲存過程中設置它,但這不是預設行為。文件中設置XACT_ABORT
on vs off的描述是:當 SET XACT_ABORT 為 ON 時,如果 Transact-SQL 語句引發執行時錯誤,則整個事務將終止並回滾。
當 SET XACT_ABORT 為 OFF 時,在某些情況下,只有引發錯誤的 Transact-SQL 語句被回滾並且事務繼續處理。根據錯誤的嚴重程度,即使 SET XACT_ABORT 為 OFF,也可能回滾整個事務。OFF 是 T-SQL 語句中的預設設置,而 ON 是觸發器中的預設設置。
SET XACT_ABORT
什麼時候ON
,呼叫故障過程會在 SSMS 中返回消息,例如:Msg 8152, Level 16, State 14, Procedure spProcName, Line 298 [Batch Start Line 5] String or binary data would be truncated. Completion time: 2021-04-26T10:51:00.8420902+10:00
SSMS 中的第一行是紅色的。
當
SET XACT_ABORT
is時OFF
,呼叫故障過程包括一條附加消息:Msg 8152, Level 16, State 14, Procedure spProcName, Line 298 [Batch Start Line 5] String or binary data would be truncated. The statement has been terminated. Completion time: 2021-04-26T10:53:52.5951780+10:00
特別是,當您看到以下消息時,這意味著過程中錯誤語句之前的語句已被送出:
The statement has been terminated.