SQL Server 2000:如何退出存储过程?

Ian*_*oyd 60 t-sql sql-server stored-procedures sql-server-2000 flow-control

如何在存储过程中退出?

我有一个存储过程,我想尽早摆脱(尝试调试).我已经打过电话RETURN,并RAISERROR和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]
Run Code Online (Sandbox Code Playgroud)

我知道它继续运行,因为我遇到了进一步的错误.我看不到任何印刷品.如果我注释掉大部分存储过程:

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]
   */
Run Code Online (Sandbox Code Playgroud)

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

before raiserror
Server: Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 5
this is a raised error
before return
Run Code Online (Sandbox Code Playgroud)

所以问题是:如何摆脱SQL Server中的存储过程?

Ada*_*Dev 83

您可以使用RETURN立即停止执行存储过程.引自网上书籍:

从查询或过程无条件退出.RETURN是立即完成的,可以在任何时候用于退出过程,批处理或语句块.不执行RETURN之后的语句.

出于偏执,我尝试了例子,它确实输出了PRINT并立即停止执行.

  • 如果您已开始交易或打开游标,请小心退出程序. (5认同)
  • 这在 TRY-CATCH 中可行吗?因此,如果我在 TRY 中调用 RETURN,它会执行 CATCH 吗? (2认同)

And*_*mar 28

除非您指定严重性为20或更高,raiserror否则不会停止执行.请参阅MSDN文档.

正常的解决方法是return在每个之后包括raiserror:

if @whoops = 1
    begin
    raiserror('Whoops!', 18, 1)
    return -1
    end
Run Code Online (Sandbox Code Playgroud)

  • @Forgotten Semicolon:是的,所以在大多数情况下,`raiserror`赢得了奖项,功能以无人预期的方式运行(以及黄金错字奖杯) (26认同)

For*_*lon 10

把它放进去TRY/CATCH.

当RAISERROR在TRY块中以11或更高的严重性运行时,它将控制转移到相关的CATCH块

参考:MSDN.

编辑: 这适用于MSSQL 2005+,但我看到你现在已经澄清你正在使用MSSQL 2000.我会留在这里作为参考.

  • +1 SQL Server 2000,所以无法回答我的问题.但对于试图进行异常处理的人来说,它可能是一种有用的技术 (4认同)

Ian*_*oyd 9

我想出为什么RETURN不能无条件地从存储过程返回.我看到的错误是在编译存储过程时 - 而不是在执行时.

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

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure
Run Code Online (Sandbox Code Playgroud)

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

但是当您实际执行存储过程时,SQL Server会编译它,并生成查询计划.

我的错误没有发生在第114行,它第114行.SQL Server无法编译存储过程,这就是它失败的原因.

这就是为什么RETURN不回归,因为它还没有开始.

  • 当然,我想在不指定列的情况下对插入进行编码。现在我必须指定它们,添加到源表的其他列将丢失。 (2认同)

Dam*_*vic 5

这在这里有效。

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
Run Code Online (Sandbox Code Playgroud)

退货

before raiserror
Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 7
this is a raised error
Run Code Online (Sandbox Code Playgroud)


JDP*_*ham 5

这看起来像是很多代码,但这是我发现的最好的方法。

    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
Run Code Online (Sandbox Code Playgroud)