为什么处理有时会终止,有时不会

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”的对象。

这意味着该进程在抛出错误时终止。

那么为什么该过程因“创建”而终止,而不因“插入”而终止?

Ran*_*gen 5

您可以使用 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_ABORTRAISERROR才不是。新的应用程序应该使用THROW而不是RAISERROR.

来源