从TRY CATCH中的单个语句捕获多个错误消息

时间:2010-09-13 01:55:04

标签: sql sql-server-2008 tsql try-catch

我正在几个列和表上运行一批语句,并希望检索有关发生错误的信息。

该语句是类型更改(varchar到nvarchar),当它失败时,它似乎返回2个错误。

  

消息5074,级别16,状态1,行1对象'DF_XXX_YYY'是   依赖于列'YYY'。

     

Msg 4922,Level 16,State 9,Line 1 ALTER   表格ALTER COLUMN描述因一个或多个对象而失败   访问此列。

但是,当我将其包装在TRY/CATCH块中并选择ERROR_MESSAGE()时,它只返回第二个错误:

  

ALTER TABLE ALTER COLUMN描述失败,因为一个或多个   对象访问此列。

理想情况下,我会让它返回第一条消息,因为这会提供更多信息。

确切的SQL语句是:

begin try
    alter table XXX
    alter column YYY
    nvarchar(200)
end try
begin catch
    select ERROR_MESSAGE(), ERROR_LINE(), ERROR_NUMBER(), ERROR_PROCEDURE(), ERROR_SEVERITY(), ERROR_STATE()
end catch

有谁知道如何检索更多信息? (@@ERROR也会返回第二个错误)

3 个答案:

答案 0 :(得分:3)

我知道这有点旧,但值得在这里重复。这是sql的错误函数的限制,但看起来它们正在为将来的版本寻址。

Social MSDN question - sql inner exception error

  

是的,这是error_xxxxx()函数的限制。当有多个错误消息时,它们仅提供有关其中一条消息的信息 - 并不总是提供最丰富的信息。

     

在下一版本的SQL Server中,代号为Denali,有一个新的命令THROW,您可以在catch处理程序中使用它,并重新报告错误,因此您不必自己处理。当您使用THROW时,两个错误都将被重新加载

答案 1 :(得分:3)

根据您的需要以及您运行此脚本的帐户的权限,您可以使用DBCC OUTPUTBUFFER(@@spid)

在阅读Erland Sommarskog的Error Handling article时,我发现了这个想法。他链接到一个程序spGET_ErrorMessage

不幸的是,我在SQL Server 2008上的测试脚本中没有完全工作,所以我不确定缓冲区格式是否已经改变但是它可能会有一点点调整!

CREATE TABLE #foo
(
c INT DEFAULT(0)
)
ALTER TABLE #foo ALTER COLUMN c VARCHAR(10)

GO
EXEC spGET_LastErrorMessage

实际输出

Msg 5074, Level 16, State 1, Line 2
The object 'DF__#foo___________c__6DCC4D03' is dependent on column 'c'.

    Msg 4922, Level 16, State 9, Line 2
    ALTER TABLE ALTER COLUMN c failed because one or more objects access this column.

声明的输出

errNumber            errState    errLevel    errMessage                                                                               errInstance                                                                                                                     errProcedure    errLine
-------------------- ----------- ----------- ---------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------- --------------- -----------
5074                 1           16          The object 'DF__#foo___________c__6DCC4D03' is dependent on column 'c'.                  MARTINHP                                                                                                                        NULL            2
4922                 9           16          The object 'DF__#foo___________c__6DCC4D03' is dependent on column 'c'.ALTER TABL        MARTINHP 䄀䰀吀䔀刀 䌀伀䰀唀䴀一 挀 昀愀椀氀攀搀 戀攀挀愀甀猀攀 漀渀攀 漀爀 洀漀爀攀 漀戀樀攀挀琀猀 愀挀挀攀猀猀 琀栀椀         NULL            117

答案 2 :(得分:3)

MikeCov已经回答了这个问题,但我不想相信未来的文档。现在是未来,所以我对此进行了测试,并确认THROW确实返回了所有错误消息。

您可以使用以下脚本重现此内容。一次运行一个注释之间的每个部分以查看输出。

/*Create tables */

CREATE TABLE dbo.test 
(
columna int primary key
)
GO

CREATE TABLE dbo.test2
(
columnb int 
)
GO

/*Create foreign key between these tables*/
ALTER TABLE dbo.test2  WITH CHECK ADD  CONSTRAINT [FK_test_to_test] FOREIGN KEY(columnb)
REFERENCES dbo.test  (columna)
GO
ALTER TABLE dbo.test2 CHECK CONSTRAINT [FK_test_to_test] 
GO

/* TEST 1 - only returns the last error message */
BEGIN TRY
    ALTER TABLE dbo.test 
    ALTER Column columna varchar
END TRY
BEGIN CATCH
    DECLARE  @ERROR_MESSAGE NVARCHAR(2048) = ERROR_MESSAGE()
    RAISERROR (@ERROR_MESSAGE,16,16)
END CATCH       

/* TEST 2 - Returns both messages, YAY */
BEGIN TRY
    ALTER TABLE dbo.test 
    ALTER Column columna varchar
END TRY
BEGIN CATCH
    THROW;
END CATCH       


/* Clean up */
DROP TABLE dbo.test2
DROP TABLE dbo.test