raiserror error_number error_msg 在SQL 2012居然不能用了!
那要如何滿足SQL 2005 ~ SQL 2012 透過 RAISERROR 來判斷@@ERROR不為0的做法呢?
最近有一支Store Procedure,裡面有使用RAISERROR。而操作的方式是執行它後,並讀取@@ERROR的值來判斷有沒有錯誤,如下,
CREATE PROC RaiseErrorTest
AS
BEGIN
RAISERROR 13001 'this is 13001 error';
END
GO
DECLARE @errNum INT;
SET @errNum = 0;
EXEC RaiseErrorTest;
SET @errNum = @@ERROR;
--如果沒有錯誤,就commit交易
IF @errNum = 0
BEGIN
PRINT '執行OK Commit'
END
ELSE
BEGIN
PRINT '執行失敗 Rollback'
END
執行結果會顯示「執行失敗 Rollback」,如下,
Msg 13001, Level 16, State 1, Procedure RaiseErrorTest, Line 4
this is 13001 error
執行失敗 Rollback
但是在SQL 2012中一執行到該Store Procedure,就發生以下的錯誤,
Msg 102, Level 15, State 1, Procedure RaiseErrorTest, Line 4
接近 '13001' 之處的語法不正確。
原因是因為我們使用了以下的RAISERROR語法過期了(從Sybase來的,可參考:raiserror)
而在SQL 2008R2就說未來版本不Support以上的寫法(SQL 2012還真的給我不Support)! 請參考:Deprecated Database Engine Features in SQL Server 2008 R2
不過,那為何那支Store Procedure,可以被建立到SQL 2012的DB之中呢?
因為那個DB是後SQL 2005備份好之後,再Restore到SQL 2012上,所以如果要重新將該Store Procedure執行到該DB的話,就會發生同樣的問題。
知道了問題所在就要加以調整它,如下,
CREATE PROC RaiseErrorTest2
AS
BEGIN
RAISERROR('this is 13001 error', 10, 1);
END
GO
再執行以下的SQL,
DECLARE @errNum INT;
SET @errNum = 0;
EXEC RaiseErrorTest2;
SET @errNum = @@ERROR;
IF @errNum = 0
BEGIN
PRINT '執行OK Commit'
END
ELSE
BEGIN
PRINT '執行失敗 Rollback'
END
但執行結果卻顯示「執行OK Commit」,天呀! 我的@@ERROR的值變成0了!如下,
this is 13001 error
執行OK Commit
表示如果使用RAISERROR('this is 13001 error', 10, 1)的方式,@@ERROR的值卻是0。
於是想要用THROW,但這樣呼叫的程式也要一併修改,就要調查程式中有多少使用到這種方式,然後加以調整,但是THROW又不能用在SQL 2012之前的版本。
…
於是筆者想到一個很瞎的作法,但卻能暫時滿足SQL 2005 ~ SQL 2012的這種透過 RAISERROR 來判斷@@ERROR不為0的做法。
就是使用RAISERROR(msg_id , 10, 1),因為使用msg_id的話,需要透過 sp_addmessage 將訊息加入SQL之中,如果沒有的話,就會產生錯誤。
所以利用這錯誤,@@ERROR就會變成不為0,呼叫的程式就可以判斷了,如下,
CREATE PROC RaiseErrorTest3
AS
BEGIN
RAISERROR(50001, 10, 1);
END
GO
再執行以下的SQL,
DECLARE @errNum INT;
SET @errNum = 0;
EXEC RaiseErrorTest3;
SET @errNum = @@ERROR;
IF @errNum = 0
BEGIN
PRINT '執行OK Commit'
END
ELSE
BEGIN
PRINT '執行失敗 Rollback'
END
執行結果會顯示「執行失敗 Rollback」(只是@@ERROR的值變成了18054,而不是我們要的50001,但針對我們舊有「只判斷@@ERROR不為0」的做法算是可以相容過去),如下,
Msg 18054, Level 16, State 1, Procedure RaiseErrorTest3, Line 4
Error 50001, severity 10, state 1 was raised, but no message with that error number was found in sys.messages. If error is larger than 50000, make sure the user-defined message is added using sp_addmessage.
執行失敗 Rollback
參考資料
Was this undocumented RAISERROR syntax ever documented and subsequently deprecated?
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^