如果其中一个查询失败,存储过程会失败吗?

xMe*_*orx 3 sql sql-server stored-procedures

假设我有一个带有SELECT, INSERTandUPDATE语句的存储过程。

事务块内没有任何内容。也没有Try/Catch块。我也XACT_ABORT设置为OFF。

如果INSERT失败了,还有可能UPDATE继续发生吗?

INSERT失败的原因是因为我将空值传递给不允许这样做的列。我只能访问程序抛出的调用存储过程的异常,据我所知,它没有任何严重性级别。

Ala*_*lan 5

潜在的。这取决于失败的严重程度。

用户代码错误通常为 16。

任何超过 20 都是自动失败。

重复的密钥阻塞插入将是 14,即非致命的。

将 NULL 插入不支持它的列 - 这被视为用户代码错误 (16) - 因此不会导致批处理停止。该UPDATE会照常举行。

另一个主要因素是批处理是否将 XACT_ABORT 配置为 ON。这将导致中止整个批次的任何失败。

这是一些进一步的阅读:

错误列表和严重性级别 in-sql-server-with-catalog-view-sysmessages

sql-server 中的异常错误处理

对于 XACT_ABORT

https://www.red-gate.com/simple-talk/sql/t-sql-programming/defensive-error-handling/

https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql

为了了解存储过程中任何步骤的结果,具有适当权限的人(例如管理员)将需要编辑存储过程并捕获错误消息。这将提供有关存储过程进度的反馈。非结构化错误(即不在 try/catch 中)代码为 0 表示成功,否则它将包含错误代码(我认为对于 NULL 插入将是 515)。正如评论中提到的那样,这是不理想的,因为它仍然不会导致批处理停止,但它会警告您存在问题。

最简单的例子:

DECLARE @errnum AS int;
-- Run the insert code
SET @errnum = @@ERROR;
PRINT 'Error code: ' + CAST(@errornum AS VARCHAR);
Run Code Online (Sandbox Code Playgroud)

错误处理可能是一个复杂的问题;它需要对数据库结构和预期的传入数据有深入的了解。

选项可以包括使用中间步骤(如 HLGEM 所述)、修改INSERT包含ISNULL / COALESCE语句以清除空值、检查客户端的数据以消除麻烦的问题等。如果您知道希望插入的行数,则存储过程可以SET @Rows=@@ROWCOUNT以与SET @errnum = @@ERROR.

如果您对存储的 proc 没有权限,也没有能力说服管理员修改它……那么您无能为力。

如果您有权直接对数据库运行您自己的查询(而不是仅通过存储的 proc 或视图),那么您可以通过对原始数据运行您自己的查询来推断结果,执行存储的 proc 更新,然后重新- 运行您的查询并寻找更改。如果您有权限,也可以尝试查询事务日志(fn_dblog)或错误日志(sp_readerrorlog)。

  • 事情是出于数据完整性的原因,如果一个步骤失败,您通常希望所有步骤都回滚。所以我个人会修复存储的过程来做到这一点并正确地冒出错误。如果您创建一个表变量来存储有关步骤或正在输入的数据或错误的信息并在每个步骤之后填充,那么当您回滚该信息时,该信息仍然可用并且可以插入到实际表中,以便您可以准确地查找内容发生了。 (2认同)