代码之家  ›  专栏  ›  技术社区  ›  Ian Boyd

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

  •  58
  • Ian Boyd  · 技术社区  · 15 年前

    如何在存储过程中间退出?

    我有一个存储过程,希望在其中尽早退出(在尝试调试它时)。我试过打电话 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]
    

    我知道它一直在运行,因为我在更远的地方遇到了一个错误。我看不到我的 印刷品 . 如果我注释掉存储过程的大部分:

    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中的存储过程中摆脱出来?

    7 回复  |  直到 11 年前
        1
  •  79
  •   bluish dmajkic    13 年前

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

    无条件退出查询或 程序。立即归还 完整,可随时使用 退出程序、批处理或 语句块。陈述 不执行后续返回。

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

        2
  •  29
  •   Andomar    15 年前

    除非您指定的严重性为20或更高, raiserror 不会停止执行。查看 MSDN documentation .

    正常的解决方法是包括 return 每一次之后 随机误差 :

    if @whoops = 1
        begin
        raiserror('Whoops!', 18, 1)
        return -1
        end
    
        3
  •  10
  •   Forgotten Semicolon adrianm    15 年前

    把它放进一个 TRY/CATCH .

    当raiserror以严重性运行时 在一个试块中有11个或更多,它 将控制权转移到关联的 挡块

    参考文献: MSDN .

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

        4
  •  8
  •   Ian Boyd    15 年前

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

    考虑虚拟存储过程:

    CREATE PROCEDURE dbo.foo AS
    
    INSERT INTO ExistingTable
    EXECUTE LinkedServer.Database.dbo.SomeProcedure
    

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

    但当你真的 执行 存储过程,然后是SQL Server 编译 并生成查询计划。

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

    这就是为什么 返回 不会回来,因为它甚至没有 起动 但是。

        5
  •  4
  •   Damir Sudarevic    15 年前

    这在这里有效。

    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
  •  4
  •   JDPeckham    12 年前

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

        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
    
        7
  •  1
  •   cjk    15 年前

    因为你没有 BEGIN END 声明。您不应该只看到打印件或运行此语句时出错 Statement Completed (或者类似的东西)。