SQLServer2000: 如何退出存储过程?

如何在存储过程中退出?

我有一个存储过程,我希望尽早摆脱(同时尝试调试它)。我试着调用 RETURNRAISERROR,但是 sp 一直在运行:

CREATE PROCEDURE dbo.Archive_Session @SessionGUID uniqueidentifier AS


print 'before raiserror'
raiserror('this is a raised error', 18, 1)
print 'before return'
return -1
print 'after return'


[snip]

我知道它一直在运行,因为我在后面遇到了一个错误。我没看到我的 指纹。如果注释掉大部分存储过程:

CREATE PROCEDURE dbo.Archive_Session @SessionGUID uniqueidentifier AS


print 'before raiserror'
raiserror('this is a raised error', 18, 1)
print 'before return'
return -1
print 'after return'


/*
[snip]
*/

然后我没有得到我的错误,我看到了结果:

before raiserror
Server: Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 5
this is a raised error
before return

因此,问题是: 如何摆脱 SQLServer 中的存储过程?

176538 次浏览

放到 TRY/CATCH里。

当 RAISERROR 以严重性运行时 如果 TRY 块中的值为11或更高,则 将控制权转移到关联的 CATCH 模块

参考资料: MSDN

编辑: 这适用于 MSSQL 2005 + ,但是我看到您现在已经澄清了您正在使用 MSSQL 2000。我把这个留在这里作参考。

除非您指定的严重性为20或更高,否则 raiserror将不会停止执行。

通常的解决办法是在每次 raiserror之后加入一个 return:

if @whoops = 1
begin
raiserror('Whoops!', 18, 1)
return -1
end

可以使用 RETURN立即停止存储过程的执行:

无条件退出查询或 程序 完整的,可以在任何时候使用 退出过程、批处理或 语句块 不执行。

出于多疑,我尝试了你的例子,它确实输出 PRINT 并立即停止执行。

这个在这里可以用。

ALTER PROCEDURE dbo.Archive_Session
@SessionGUID int
AS
BEGIN
SET NOCOUNT ON
PRINT 'before raiserror'
RAISERROR('this is a raised error', 18, 1)
IF @@Error != 0
RETURN
PRINT 'before return'
RETURN -1
PRINT 'after return'
END
go


EXECUTE dbo.Archive_Session @SessionGUID = 1

报税表

before raiserror
Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 7
this is a raised error

我知道为什么 RETURN不能从存储过程无条件返回了。我看到的错误是当存储过程是 编译完毕时-而不是当它被执行时。

考虑一个虚构的存储过程:

CREATE PROCEDURE dbo.foo AS


INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

即使这个存储过程包含一个错误(也许是因为对象有不同数量的列,也许表中有一个时间戳列,也许存储过程不存在) ,您仍然可以对它进行 拯救。您可以保存它,因为您正在引用链接服务器。

但是当您实际 执行存储过程时,SQLServer 再 编译它,并生成一个查询计划。

我的错误不是 发生了在第114行,而是 开始在第114行。SQLServer 无法编译存储过程,这就是它失败的原因。

这就是为什么 RETURN不返回,因为它甚至还没有 开始了

这是因为您没有 BEGINEND语句。您不应该看到打印或运行此语句的错误,只能看到 Statement Completed(或类似的内容)。

这看起来有很多代码,但是我找到的最好的方法。

    ALTER PROCEDURE Procedure
AS


BEGIN TRY
EXEC AnotherProcedure
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;


SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();


RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
RETURN --this forces it out
END CATCH


--Stuff here that you do not want to execute if the above failed.


END --end procedure