2017-07-14 58 views
0

假設我有一個SELECTINSERTUPDATE語句的存儲過程。如果其中的某個查詢失敗,存儲過程是否會失敗?

事務塊內沒有內容。也沒有Try/Catch塊。 我也有XACT_ABORT設置爲OFF。

如果INSERT失敗,UPDATE仍然有可能發生?

INSERT失敗的原因是因爲我將空值傳遞給不允許的列。我只能訪問被稱爲存儲過程的程序拋出的異常,並且它沒有任何嚴重性級別,據我所知。

+0

這取決於您的過程中的錯誤處理代碼:如果您有'TRY ... CATCH'塊。 – Dai

+0

沒有嘗試捕捉塊 – xMetalDetectorx

+1

誰控制存儲過程?你的編輯有點不清楚,這聽起來像你改變了你的問題。您的原始問題是:更新是否仍然可以發生?答:是的。你已經添加了一些額外的陳述,這些陳述並沒有改變你的答案,也沒有改變你的要求。現在你的新問題意味着:我不控制proc;我如何從中獲得體面的錯誤信息? – Alan

回答

3

可能。這取決於失敗的嚴重程度。

用戶代碼錯誤通常是16.

超過20的任何情況都是自動失敗。

重複密鑰阻塞插入將是14,即非致命的。

將NULL插入到不支持它的列中 - 這被視爲用戶代碼錯誤(16) - 因此不會導致批處理暫停。 UPDATE將繼續。

另一個主要因素是如果批處理的XACT_ABORT配置爲ON。這將導致任何失敗中止整批。

下面是一些進一步閱讀:

list-of-errors-and-severity-level-in-sql-server-with-catalog-view-sysmessages

exceptionerror-handling-in-sql-server

而對於XACT_ABORT

https://www.red-gate.com/simple-talk/sql/t-sql-programming/defensive-error-handling/

https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql

爲了理解存儲過程中任何步驟的結果,具有適當權限的人員(例如,管理員)需要編輯存儲的proc並捕獲錯誤消息。這將給出關於存儲過程的進度的反饋。一個非結構化錯誤(即不在try/catch中)代碼爲0表示成功,否則將包含錯誤代碼(我認爲對於NULL插入來說,它將爲515)。這是非常理想的,因爲它仍然不會導致批處理停止,但會警告您存在問題。

最簡單的例子:

DECLARE @errnum AS int; 
-- Run the insert code 
SET @errnum = @@ERROR; 
PRINT 'Error code: ' + CAST(@errornum AS VARCHAR); 

錯誤處理可以是一個複雜的問題;它需要對數據庫結構和預期傳入數據有重要的瞭解。

選項可以包括使用中間步驟(如HLGEM所述),修改INSERT以包含ISNULL/COALESCE語句以清除空值,檢查客戶端上的數據以消除麻煩的問題等。如果知道預計要插入的行數,則存儲的proc可以返回SET @[email protected]@ROWCOUNT,方法與SET @errnum = @@ERROR相同。

如果您對存儲過程沒有權限,並且沒有能力說服管理員修改它,那麼您可以做的事情並不多。

如果您有權直接對數據庫運行自己的查詢(而不是通過存儲過程或視圖),那麼您可以通過對原始數據運行自己的查詢來推斷結果,執行存儲過程更新,然後重新運行您的查詢並查找更改。如果您有權限,則還可以嘗試查詢事務日誌(fn_dblog)或錯誤日誌(sp_readerrorlog)。

+0

感謝您的所有信息! XACT_ABORT對我來說是關閉的。我只能訪問我的程序拋出的異常,而且我沒有看到嚴重程度。 「插入」失敗的原因是因爲我將空值傳遞給不接受空值的列。 – xMetalDetectorx

+1

由於數據完整性原因,您通常希望所有步驟都在發生故障時進行回滾。所以我個人會修復存儲過程來做到這一點,並適當地冒出錯誤。如果您創建一個表變量來存儲步驟或輸入數據的信息,或者在每個步驟之後填充錯誤和填充信息,那麼當您回滾該信息仍然可用時,可以將其插入真實表格中,以便您可以準確查找發生了。 – HLGEM