当对象不存在时处理事务错误

gr9*_*28x 6 sql transactions try-catch

我在MSDN Lbrary中发现和文章解释说try/catch不能处理无法找到对象时抛出的错误.所以,即使我在try/catch中包装一个事务,回滚短语也不会执行:

BEGIN TRY
BEGIN TRANSACTION

    SELECT 1 FROM dbo.TableDoesNotExists
    PRINT ' Should not see this'
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION
    SELECT
            ERROR_MESSAGE()
END CATCH

--PRINT 'Error Number before go: ' + CAST(@@Error AS VARCHAR)

go
PRINT 'Error Count After go: ' + CAST(@@Error AS VARCHAR)
PRINT 'Transaction Count ' + CAST(@@TRANCOUNT AS VARCHAR)
Run Code Online (Sandbox Code Playgroud)

当对象不存在时,特别是涉及事务时,建议的方法是处理抛出的错误.我应该用这一段代码代替最后两个打印语句:

IF @@ERROR <> 0 AND @@TRANCOUNT > 0
BEGIN   
    PRINT 'Rolling back txn'
    ROLLBACK TRANSACTION
END 

go

PRINT 'Transaction Count again: ' + CAST(@@TRANCOUNT AS VARCHAR)
Run Code Online (Sandbox Code Playgroud)

Ton*_*ony 0

为什么要尝试从不存在的表中检索数据?

\n\n

数据库的基本构建块是表。不知道架构中的内容本质上是试图将 SQL 用作动态语言,但事实并非如此。

\n\n

我会重新考虑你的设计;如果不了解有关数据库中的表及其预期用途的更多信息,其他人很难在这方面提供帮助。请为您的问题添加更多信息。

\n\n

编辑\n我读过 BOL,当对象不存在时处理错误的推荐方法如下:

\n\n
\n

您可以使用 TRY\xe2\x80\xa6CATCH 通过在 TRY 块内\n 单独的批处理中执行\n 错误生成代码来处理编译或语句级重新编译期间发生的错误。\n 例如,您可以通过将代码放入存储过程中或使用 sp_executesql 执行动态 Transact-SQL 语句来完成此操作。这允许 TRY\xe2\x80\xa6CATCH 在比错误发生时更高的执行级别捕获错误。

\n
\n\n

我使用以下过程对此进行了测试

\n\n
CREATE PROCEDURE [dbo].[BrokenProcedure]\nAS\nBEGIN\n    SET NOCOUNT ON;\n    SELECT * FROM MissingTable\nEND\nGO\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后在块内调用它TRY..CATCH

\n\n
BEGIN TRY\n    PRINT 'Error Number before: ' + CAST(@@Error AS VARCHAR)\n    EXECUTE [dbo].[BrokenProcedure] \n    PRINT ' Should not see this'\nEND TRY\nBEGIN CATCH\n    PRINT 'Error Number in catch: ' + CAST(@@Error AS VARCHAR)\nEND CATCH\n
Run Code Online (Sandbox Code Playgroud)\n\n

产生以下输出:

\n\n
\n

之前的错误编号:0

\n\n

catch 中的错误号:208

\n
\n\n

这不是一个完美的解决方案,因为您必须为所有表访问创建过程(或使用动态 SQL),但这是 MS 推荐的方法。

\n