Ciu*_*caS 3 sql-server stored-procedures sql-server-2012
这个问题应该很简单,但我无法弄清楚答案,也不知道为什么我的存储过程不起作用.
CREATE PROCEDURE spTest_Delete
@ID int
AS
begin tran
declare @err int
declare @errMesage nvarchar(max)
set @errMesage = ''
set @err = 0
delete from Test
where ID = @ID
set @err = @@ERROR
set @errMesage = ERROR_MESSAGE()
if @err = 0
commit tran
else
begin
RAISERROR(N'Could not delete !Error nr: %d. Message: %s', 1, 16, @err, @errMesage)
rollback tran
end
Run Code Online (Sandbox Code Playgroud)
这个过程运行正常,但是如果对delete语句有FK约束,它会遇到错误(这很好),我想抓住错误.
消息547,级别16,状态0,过程spTest_Delete,第12行
DELETE语句与REFERENCE约束"FK_TEstFK_Test"冲突.冲突发生在数据库"Test",表"dbo.Test",列"ID"中.该语句已终止.无法删除!
错误号:547.消息:(null)消息50000,级别1,状态16
我的消息变量总是为null,即使该delete语句引发错误.
Rah*_*thi 10
尝试使用 TRY CATCH 并捕获您的错误,如下所示:
BEGIN TRY
delete from Test
where ID = @ID
END TRY
BEGIN CATCH
SET @ErrorMessage = ERROR_MESSAGE()
SET @ErrorSeverity = ERROR_SEVERITY()
SET @ErrorState = ERROR_STATE()
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState)
BREAK
END CATCH
Run Code Online (Sandbox Code Playgroud)
您可能希望在过程中开始使用TRY..CATCH块
实现Transact-SQL的错误处理,类似于Microsoft Visual C#和Microsoft Visual C++语言中的异常处理.一组Transact-SQL语句可以包含在TRY块中.如果TRY块中发生错误,则将控制权传递给包含在CATCH块中的另一组语句.
所以你的程序可以改写为:
CREATE PROCEDURE spTest_Delete @ID INT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION
DELETE
FROM Test
WHERE ID = @ID;
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH
END
Run Code Online (Sandbox Code Playgroud)
此外,请注意您作为单个删除语句运行.这意味着它不需要包含在事务中.这个问题解释了原因.
你的代码变成了这样:
CREATE PROCEDURE spTest_Delete @ID INT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
DELETE
FROM Test
WHERE ID = @ID;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH
END
Run Code Online (Sandbox Code Playgroud)
为什么你@errMessage的总是NULL?因为ERROR_MESSAGE()仅在CATCH块中有效.这是用文档写的:
返回导致运行TRY ... CATCH构造的CATCH块的错误的消息文本.
通过在TRY ... CATCH构造的CATCH块范围内的任何位置使用这些函数来检索错误信息.如果在CATCH块的范围之外调用,则错误函数将返回NULL.