在.net中,当我使用SqlCommand
并调用一个使用RAISERROR
抛出的存储过程时,我可以读取由该过程设置的输出变量。但是,从T-SQL批处理中调用该过程时,OUTPUT
参数看起来完全没有设置。如何在调用RAISERROR之前读取由存储过程设置的批处理中的OUTPUT参数?
当过程调用RAISERROR
来指示错误时,如何从调用T-SQL中读取OUTPUT
参数@OUT_x
?
CREATE PROCEDURE dbo.p_x (
@OUT_x INT OUTPUT
) AS
BEGIN
SET @OUT_x = 1;
SELECT 'inner ', @OUT_x;
RAISERROR('yo', 11, 1);
END
GO
DECLARE @x INT = 0;
SELECT 'initial', @x;
BEGIN TRY
EXEC dbo.p_x @x OUTPUT;
END TRY
BEGIN CATCH
SELECT 'catch', @x;
END CATCH
SELECT 'end', @x;
输出:
------- -----------
initial 0
------ -----------
inner 1
----- -----------
catch 0
---- -----------
end 0
我证明@OUT_x被示出经由RAISERROR
抛之前其在存储过程中的值设置为1
。我预计“catch”和“end”条目是1
,但它好像OUTPUT
参数值复制只发生在成功的存储过程完成时。 I know I can read these OUTPUT
parameters when I call stored procedures through SqlCommand
- 为什么T-SQL批处理必须有任何不同?
是否有解决方法,不涉及更改存储过程?我真的希望我的存储过程在异常情况下抛出(RAISERROR
),但我还需要使用OUTPUT
参数来传递错误详细信息。
T-SQL批处理没有区别。如果你把这整段代码放到'SqlCommand'中,你会得到相同的结果。你的问题实际上是为什么'TRY .. CATCH'正在做它正在做的事情(当存储过程执行'RAISERROR'时不复制输出参数)。厄兰德[涵盖此](http:// sommarskog。se/error_handling/Part2.html#systemfunctions)在他的无与伦比的错误处理文章,但基本上,这只是它的工作方式。你不能使用'TRY .. CATCH'并且得到错误之前分配的输出参数的值。 –
@JeroenMostert'SqlCommand'返回'1'的参数就像你期望的那样。 – GSerg
@binki,@GSerg:即使你可以(并且我不知道你是否可以,我还没有测试过),这里的关键问题是'try {...} catch {...}'in托管代码与T-SQL中的TRY ... CATCH不同。我正在谈论*执行整个代码块*,包括'TRY ... CATCH',作为'SqlCommand'。你真的告诉我结果不一样吗?很显然,如果可以的话,在T-SQL之外处理错误*因为在T-SQL内部处理它们是一件很混乱的事情。但我从这个问题中收集到的,这正是这里没有的选项。 –