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

发布于 2024-08-13 08:10:36 字数 913 浏览 7 评论 0原文

如何在存储过程中退出?

我有一个存储过程,我想尽早退出(同时尝试调试它)。我尝试调用 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

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

How can I exit in the middle of a stored procedure?

I have a stored procedure where I want to bail out early (while trying to debug it). I've tried calling RETURN and RAISERROR, and the sp keeps on running:

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]

I know it keeps running because I encounter an error further down. I don't see any of my prints. If I comment out the bulk of the stored procedure:

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]
   */

Then I don't get my error, and I see the results:

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

So the question is: how do I bail out of a stored procedure in SQL Server?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

七禾 2024-08-20 08:10:36

您可以使用RETURN立即停止存储过程的执行。引用自联机丛书

无条件退出查询或
程序。立即退货
完整且可以随时使用
退出过程、批处理或
语句块。声明称
follow RETURN 不执行。

出于偏执,我尝试了你的例子,它确实输出了打印并立即停止执行。

You can use RETURN to stop execution of a stored procedure immediately. Quote taken from Books Online:

Exits unconditionally from a query or
procedure. RETURN is immediate and
complete and can be used at any point
to exit from a procedure, batch, or
statement block. Statements that
follow RETURN are not executed.

Out of paranoia, I tried yor example and it does output the PRINTs and does stop execution immediately.

你げ笑在眉眼 2024-08-20 08:10:36

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

正常的解决方法是在每个 raiseerror 之后包含一个 return

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

Unless you specify a severity of 20 or higher, raiserror will not stop execution. See the MSDN documentation.

The normal workaround is to include a return after every raiserror:

if @whoops = 1
    begin
    raiserror('Whoops!', 18, 1)
    return -1
    end
楠木可依 2024-08-20 08:10:36

将其放入 TRY/CATCH 中。

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

参考:MSDN

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

Put it in a TRY/CATCH.

When RAISERROR is run with a severity
of 11 or higher in a TRY block, it
transfers control to the associated
CATCH block

Reference: MSDN.

EDIT: This works for MSSQL 2005+, but I see that you now have clarified that you are working on MSSQL 2000. I'll leave this here for reference.

红玫瑰 2024-08-20 08:10:36

我弄清楚为什么 RETURN 没有无条件地从存储过程返回。我看到的错误是在编译存储过程时出现的错误,而不是在执行存储过程时出现的错误。

考虑一个假想的存储过程:

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

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

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

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

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

i figured out why RETURN is not unconditionally returning from the stored procedure. The error i'm seeing is while the stored procedure is being compiled - not when it's being executed.

Consider an imaginary stored procedure:

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

Even though this stord proedure contains an error (maybe it's because the objects have a differnet number of columns, maybe there is a timestamp column in the table, maybe the stored procedure doesn't exist), you can still save it. You can save it because you're referencing a linked server.

But when you actually execute the stored procedure, SQL Server then compiles it, and generates a query plan.

My error is not happening on line 114, it is on line 114. SQL Server cannot compile the stored procedure, that's why it's failing.

And that's why RETURN does not return, because it hasn't even started yet.

话少心凉 2024-08-20 08:10:36

这在这里有效。

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

This works over here.

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

Returns

before raiserror
Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 7
this is a raised error
拥有 2024-08-20 08:10:36

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

    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

This seems like a lot of code but the best way i've found to do it.

    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
眼泪淡了忧伤 2024-08-20 08:10:36

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

Its because you have no BEGIN and END statements. You shouldn't be seeing the prints, or errors running this statement, only Statement Completed (or something like that).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文