我正在几个列和表上运行一批语句,并希望检索有关发生错误的信息。
该语句是类型更改(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
也会返回第二个错误)
答案 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