slo*_*ams 2 sql-server error-handling
DECLARE @Error int;
INSERT INTO Person.BusinessEntityContact
(BusinessEntityID
,PersonID
,ContactTypeID)
VALUES
(0,0,1);
SELECT @Error = @@ERROR;
PRINT ‘The Value of @Error is ‘ + CONVERT(varchar, @Error);
Run Code Online (Sandbox Code Playgroud)
我有 :
消息 547,级别 16,状态 0,第 4 行 INSERT 语句与 FOREIGN KEY 约束“FK_BusinessEntityContact_Person_PersonID”相冲突......该语句已终止。@Error 的值为 547
这意味着在抛出错误后该过程仍在继续。
但是,如果我尝试创建一个表(运行以下脚本两次以触发错误)为:
CREATE TABLE OurIFTest(
Col1 int PRIMARY KEY
);
IF @@ERROR != 0
PRINT 'Problems!';
ELSE
PRINT 'Everything went OK!';
Run Code Online (Sandbox Code Playgroud)
然后我得到了
消息 2714,级别 16,状态 6,第 2 行 数据库中已经有一个名为“OurIFTest”的对象。
这意味着该进程在抛出错误时终止。
那么为什么该过程因“创建”而终止,而不因“插入”而终止?
您可以使用 SET XACT_ABORT 在错误中强制执行相同的行为
SET XACT_ABORT ON;
Run Code Online (Sandbox Code Playgroud)
从文档:
指定当 Transact-SQL 语句引发运行时错误时 SQL Server 是否自动回滚当前事务。
默认情况下,XACT_ABORT = OFF
这意味着不同的错误会产生不同的结果。
要强制错误行为相同,请SET XACT_ABORT ON;
在脚本的开头添加。
用你的例子测试
SET XACT_ABORT ON;
DECLARE @Error int;
INSERT INTO Person.BusinessEntityContact
(BusinessEntityID
,PersonID
,ContactTypeID)
VALUES
(0,0,1);
SELECT @Error = @@ERROR;
PRINT 'The Value of @Error is ‘ + CONVERT(varchar, @Error)'
Run Code Online (Sandbox Code Playgroud)
显示唯一的错误:
消息 547,级别 16,状态 0,第 17 行 INSERT 语句与 FOREIGN KEY 约束“FK_Person”冲突。冲突发生在数据库“my_test”、表“Person.Person”、列“PersonID”中。
还要注意这个关于错误处理的重要声明和 SET XACT_ABORT
该
THROW
声明的荣誉SET XACT_ABORT
。RAISERROR
才不是。新的应用程序应该使用THROW
而不是RAISERROR
.