【问题标题】:SQL Server try-catch inner exception message conundrumSQL Server try-catch 内部异常消息难题
【发布时间】:2010-12-03 21:00:17
【问题描述】:

下面的 SQL 语句是一些抛出带有嵌套详细信息的异常的 SQL 的一个很好的示例。似乎在语句的 catch 部分中,我只能获取外部异常详细信息Could not create constraint. See previous errors(不是很有用!)。我想得到的是内部异常消息:

引入 FOREIGN KEY 约束 表 'TABLE2' 上的 'FK_TWO' 可能会导致 循环或多个级联路径。 指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束(你可以得到 此消息通过运行代码 没有 try-catch)。

在 Catch 块中,如何在 T-SQL 中实现?

BEGIN TRY
      BEGIN TRAN;

        CREATE TABLE TABLE1 (USER_ID INTEGER NOT NULL PRIMARY KEY, USER_NAME
            CHAR(50) NOT NULL);

        CREATE TABLE TABLE2 (AUTHOR_ID INTEGER NOT NULL PRIMARY KEY, AUTHOR_NAME
            CHAR(50) NOT NULL, LASTMODIFIEDBY INTEGER NOT NULL, ADDEDBY INTEGER NOT
            NULL);

        ALTER TABLE TABLE2 ADD CONSTRAINT FK_ONE FOREIGN KEY (LASTMODIFIEDBY)
            REFERENCES TABLE1 (USER_ID) ON DELETE CASCADE ON UPDATE CASCADE;

        ALTER TABLE TABLE2 ADD CONSTRAINT FK_TWO FOREIGN KEY (ADDEDBY)
            REFERENCES TABLE1(USER_ID) ON DELETE NO ACTION ON UPDATE CASCADE;   

        COMMIT TRAN;
END TRY
BEGIN CATCH

      DECLARE @ERROR_MSG NVARCHAR(MAX), @SEVERITY INT, @STATE INT
      SELECT @SEVERITY = ERROR_SEVERITY(), @STATE = ERROR_STATE()
            , @ERROR_MSG = ERROR_MESSAGE() + ' err src line: ' + CAST( ERROR_LINE() AS NVARCHAR(20)) + ' ' + ISNULL(ERROR_PROCEDURE(), ''); 

      ROLLBACK;
      -- RE-THROW EXCEPTION FOR DIAGNOSTIC VISIBILITY
      RAISERROR (@ERROR_MSG ,@SEVERITY, @STATE); 
END CATCH;

[编辑]

因此,经过大量搜索,似乎没有解决此问题的方法。希望他们能在未来的版本中解决这个问题。

【问题讨论】:

标签: sql-server tsql exception-handling try-catch


【解决方案1】:

您不能重新抛出原始错误。您必须抛出一个 new 错误,错误编号高于 50000,其中包含捕获的错误消息。示例见Exception handling and nested transactions

begin catch
    declare @error int, @message varchar(4000), @xstate int;
    select @error = ERROR_NUMBER()
        , @message = ERROR_MESSAGE();
raiserror ('Caught exception: %d: %s', 16, 1, @error, @message) ;
return;
end catch   

我链接的文章有一个更详尽的示例,还涵盖了强制性的 XACT_STATE() 检查以及将 try/catch 块与事务语义混合。

在下一个版本(“Denali”)中,这个问题得到了解决,因为您可以发出 throw; 不带任何参数,这将引发原始异常,就像在其他 try/catch 语言中一样。见TRY CATCH THROW: Error handling changes in T-SQL

更新

哦,我有点看对角线的帖子。如果引发更多异常,则只能捕获一个。这仍然是正确的,德纳利也是如此。但大多数情况下,引发的异常是严重性 0(这意味着它们实际上是打印,而不是异常),并且这些异常仍然作为信息消息(SqlConnection.InfoMessage 事件)发送给客户端。

【讨论】:

    【解决方案2】:

    这个问题现在没有解决办法。根据this 的说法,下一版 SQL Server 中的解决方案将是使用新的 throw 关键字,这将重新引发这两个错误。

    猜你喜欢
    • 2020-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多