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

Posted

技术标签:

【中文标题】SQL Server 2000:如何退出存储过程?【英文标题】:SQL Server 2000: How to exit a stored procedure? 【发布时间】:2010-12-24 04:30:50 【问题描述】:

如何在存储过程中退出?

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

【问题讨论】:

"欢迎来到加州酒店..." =) 呃? (填充以使我的“Guh?”查询至少 15 个字符长) 哦,等等,我明白了……“你永远不能离开”。 这个问题甚至需要被问到,这表明 SQL 有一些偏差,但话又说回来,它是一种固定在函数式语言一侧的过程方法,所以你期望什么? 【参考方案1】:

这似乎有很多代码,但这是我发现的最好的方法。

    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

【讨论】:

【参考方案2】:

您可以使用RETURN 立即停止执行存储过程。引自Books Online:

无条件退出查询或 程序。 RETURN 是立即的,并且 完整,可随时使用 退出程序、批次或 语句块。声明 follow RETURN 不会被执行。

出于偏执,我尝试了您的示例,它确实输出了 PRINT 并立即停止执行。

【讨论】:

你能想到为什么调用return不会无条件退出过程吗? 如果您已经开始一个事务或有一个打开的游标,请小心退出过程。 我不能 - 您能否发布一个完整的存储过程示例,当您运行它时,不会在返回时立即退出?只是为了让我们有一个确切的例子来回顾 这可以在 TRY-CATCH 中使用吗?因此,如果我在 TRY 中调用 RETURN,它会执行 CATCH 吗?【参考方案3】:

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

【讨论】:

【参考方案4】:

我知道为什么RETURN 不是无条件地从存储过程返回。我看到的错误是存储过程正在编译 - 而不是在执行时。

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

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

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

但是当你真正执行存储过程时,SQL Server 会编译它,并生成一个查询计划。

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

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

【讨论】:

当然你不应该在没有指定列的情况下编写插入代码。 当然我想在不指定列的情况下编写插入代码。现在我必须指定它们,添加到源表的其他列将丢失。【参考方案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

返回

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

【讨论】:

这似乎是一种更简洁/更快的输入方式。【参考方案6】:

把它放在TRY/CATCH

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

参考:MSDN。

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

【讨论】:

+1 SQL Server 2000,所以无助于回答我的问题。但对于尝试进行异常处理的人来说,这可能是一种有用的技术 我真的很喜欢这个。但是......叹息......其他新东西要学习。【参考方案7】:

除非您指定 20 或更高的严重性,raiserror 不会停止执行。请参阅MSDN documentation。

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

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

【讨论】:

“从 19 到 25 的严重级别只能由 sysadmin 固定服务器角色的成员或具有 ALTER TRACE 权限的用户指定。”来自 MSDN @Forgotten Semicolon: 是的,所以在大多数情况下,raiserror 因其功能出乎意料的功能而获奖(以及金错字奖杯) +1。不是这个问题的真正答案,而是“答案很有用”

以上是关于SQL Server 2000:如何退出存储过程?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 SQL Server 2000 调用 MySQL 存储过程?

用SQL创建存储过程的题目(SQL SERVER2000下)

SQL Server 2000 系统存储过程

在 SQL Server 2000 中删除存储过程的语法是啥?

Sql Server 2000 在安装过程中跳过CD-Key的解决方案

如何写sqlserver2000存储过程?用于批量录入数据,求解