SQL Server 中關於 @@error 的一個小誤區

在SQL Server中,我經常會看到有些前輩這樣寫:spa

if(@@error<>0)
    ROLLBACK TRANSACTION T
else
    COMMIT TRANSACTION T

一開始,我看見別人這麼寫,我就想固然的覺得它只是個計數器,每當檢測到一處錯誤時,@@error的值+1,不過就由於這個理所固然,因此杯具了...code

實際上,它並非一個計數器,它是一個動態的值,動態的標識最後一條SQL命令執行的結果,若是成功則爲0,不成功則標識錯誤碼。因此,像上面這種寫法是不妥的,舉個例子,以下:blog

SET NOCOUNT ON;
SET XACT_ABORT ON;  --執行 Transact-SQL 語句產生運行時錯誤,則整個事務將終止並回滾

BEGIN TRANSACTION T

UPDATE Test
SET a='已更新'
WHERE a='未更新'

RAISERROR ('很差意思,你沒有權限!',16,1)

SELECT GETDATE() if(@@error<>0) ROLLBACK TRANSACTION T else COMMIT TRANSACTION T

分析:事務

  按我之前的理解來講,【 RAISERROR ('很差意思,你沒有權限!',16,1) 】這裏拋出了一個錯誤,整個事務應該回滾纔對,但是,它卻沒有回滾!!那麼緣由出在哪呢?原來,問題出在"SELECT GETDATE()"這句上面!由於執行RAISERROR語句時,@@error的值不爲0(好像是5000),而當執行到下一句"SELECT GETDATE()"時,@@error的值又變爲0了!因此,後面的if語句天然沒有捕捉到任何錯誤...class

 

對策:變量

  既然找到了緣由,那解決辦法天然也少不了。用Try...CATCH語法就能夠了,語句以下:權限

SET NOCOUNT ON;
SET XACT_ABORT ON;  --執行 Transact-SQL 語句產生運行時錯誤,則整個事務將終止並回滾

BEGIN TRY
    BEGIN TRANSACTION T

    UPDATE Test
    SET a='已更新'
    WHERE a='未更新'

    RAISERROR ('很差意思,你沒有權限!',16,1)

    SELECT GETDATE()
    
    COMMIT TRANSACTION T
END TRY
BEGIN CATCH
    DECLARE @msg nvarchar(2000)=ERROR_MESSAGE()    --將捕捉到的錯誤信息存在變量@msg中               
    RAISERROR (@msg,16,1)    --此處才能拋出(好像是這樣子....)
    ROLLBACK TRANSACTION T  --出錯回滾事務
END CATCH
相關文章
相關標籤/搜索