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

时间:2017-07-14 00:41:27

标签: sql sql-server stored-procedures

假设我的存储过程包含SELECTINSERTUPDATE语句。

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

如果INSERT失败,UPDATE是否仍有可能发生?

INSERT失败的原因是因为我将空值传递给不允许该值的列。我只能访问调用存储过程的程序的异常,并且就我所见,它没有任何严重性级别。

1 个答案:

答案 0 :(得分:4)

潜在。它取决于失败的严重性级别。

用户代码错误通常为16.

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

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

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

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

在这里进一步阅读:

list-of-errors-and-severity-level-in-sql-server-with-catalog-view-sysmessages

exceptionerror-handling-in-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);

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

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

如果您对存储过程没有权限,并且无法说服管理员修改它......那么您可以做的事情并不多。

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