【问题标题】:sp_executesql inside Try & CatchTry & Catch 中的 sp_executesql
【发布时间】:2013-08-25 00:05:17
【问题描述】:
Begin Try
Declare @SQL NVarchar(Max)='Exec [MyLinkedServer].master.dbo.sp_executesql N''Drop Table [tempdb].dbo.[T1]''';
Print   @SQL;
Exec master.dbo.sp_executesql @SQL;
End Try
Begin Catch
Print Error_Message()
End Catch

当 MyLinkedServer 中不存在表 T1 时,上述脚本会失败 而不是被定向到 Catch 部分。 我错过了什么?

要明确一点:原始过程使用参数在过程内部动态构造@SQL。

谢谢!

【问题讨论】:

    标签: sql-server try-catch dynamic-sql sp-executesql


    【解决方案1】:

    不,上面的脚本没有失败,并且完全按照您的预期工作:

    Begin Try
    Declare @SQL NVarchar(Max)='Exec [MyLinkedServer].master.dbo.sp_executesql N''Drop Table [tempdb].dbo.[T1]''';
    Print   @SQL;
    Exec master.dbo.sp_executesql @SQL;
    End Try
    Begin Catch
    print 'in catch'
    Print Error_Message()
    End Catch
    
    Exec [MyLinkedServer].master.dbo.sp_executesql N'Drop Table [tempdb].dbo.[T1]'
    in catch
    Could not find server 'MyLinkedServer' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
    

    看到那个'in catch'消息了吗?是 catch 块被执行的证明。

    但是你是对的,有一个众所周知的问题是编译错误不能在它们发生的范围内被捕获。这绝对是意料之中的,就像在代码编译失败时要求 C# 程序中的 catch 块运行......这个问题在Error Handling in SQL 2005 and Later 得到了很好的详细解释。您必须创建一个外部范围来捕获内部范围中发生的编译错误。这正是您在发布的示例中所做的!

    【讨论】:

    • 谢谢,但您有一个不同的错误:您没有名为 MyLinkedServer 的链接服务器,并且此类本地错误由 Try & Catch 处理。
    • 您的 XACT_ABORT 是打开还是关闭?见Handling Errors in Server-to-Server Remote Stored Procedures
    • 我尝试了这两个选项,结果是一样的。
    • 我尝试了这两个选项,结果是一样的。看起来很奇怪的是,与“创建表 [tempdb].dbo.[T1](I Int)”相同的代码在它已经存在(严重性 11)时工作正常,但使用“删除表 [tempdb].dbo。 [T1]'(严重性 16)失败。非常感谢您的帮助。
    猜你喜欢
    • 2012-11-25
    • 1970-01-01
    • 2010-12-14
    • 2015-06-15
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多