以下SQL语句是一些使用嵌套详细信息抛出异常的SQL的一个很好的示例。似乎在语句的catch部分我只能得到外部异常细节Could not create constraint. See previous errors
(不是非常有用!)。我想得到的是内部异常消息:
引入FOREIGN KEY约束 表'TABLE2'上的'FK_TWO'可能会导致 循环或多个级联路径。 指定ON DELETE NO ACTION或ON 更新无动作,或修改其他动作 FOREIGN KEY约束(你可以得到 通过运行代码来传递此消息 没有试试)。
在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;
[编辑]
所以经过多次搜索后似乎没有解决这个问题的办法。希望他们能在未来的版本中解决这个问题。
答案 0 :(得分:9)
您无法重新抛出原始错误。您必须抛出 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;
w / o任何参数,这将引发原始异常,就像在其他try / catch语言中一样。见TRY CATCH THROW: Error handling changes in T-SQL
更新
噢,我有点读对角线的帖子。如果引发更多异常,则只能捕获一个异常。德纳利也是如此。但大多数情况下,引发的异常是严重性0(意味着它们确实是打印,而不是异常),而且仍然作为信息性消息(SqlConnection.InfoMessage
事件)传递给客户端。
答案 1 :(得分:0)
现在没有解决这个问题的方法。根据{{3}},下一版本的SQL Server中的解决方案将使用新的throw关键字,这将重新引发两个错误。