Sql server SQL Server 2000:如何退出存储过程? 如何在存储过程中间退出?< /P>

Sql server SQL Server 2000:如何退出存储过程? 如何在存储过程中间退出?< /P>,sql-server,tsql,stored-procedures,sql-server-2000,control-flow,Sql Server,Tsql,Stored Procedures,Sql Server 2000,Control Flow,我有一个存储过程,我希望尽早退出(同时尝试调试它)。我已尝试调用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 pr

我有一个存储过程,我希望尽早退出(同时尝试调试它)。我已尝试调用
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]
   */
CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure
然后我没有得到我的错误,我看到了结果:

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

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

将其放入
TRY/CATCH

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

参考文献:


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

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

正常的解决方法是在每个
错误出现后包含
返回

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

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

无条件退出查询或 程序返回是立即的,并且 完整,可在任何位置使用 退出某个过程、批处理或 语句块。声明 不执行跟随返回

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

在这里可以

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.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.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure
即使此存储过程包含错误(可能是因为对象的列数不同,可能是表中有时间戳列,可能是存储过程不存在),您仍然可以保存它。您可以保存它,因为您正在引用链接的服务器

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

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


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

因为没有
BEGIN
END
语句。您不应该看到打印或运行此语句的错误,只有
语句完成了
(或类似的内容)。

这似乎有很多代码,但这是我找到的最好的方法

    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

“欢迎来到加州酒店……”古?(填充使我的“Guh?”查询至少有15个字符长)哦,等等,我明白了…“你永远不能离开”。这个问题甚至需要被问到,这表明SQL有点不对劲,但再一次,它是固定在函数式语言一侧的过程方法论,那么您期望什么呢?“严重性级别从19到25只能由sysadmin固定服务器角色的成员或具有ALTER TRACE权限的用户指定。”来自MSDN@Forgotten分号:是的,所以在大多数情况下,
raiserror
因其功能以无人期待的方式运行而获奖(以及金奖打字奖)+1.不是对这个问题的真正回答,而是“答案很有用”“您能想出调用
return
不能无条件退出过程的任何原因吗?如果您已启动事务或有打开的游标,请小心从过程中退出。我不能-您能否发布一个完整的存储过程示例,说明当您运行它时,不会在返回时立即退出?就为了让我们有一个确切的例子来回顾这项工作,我们可以尝试一下吗?因此,如果我在TRY中调用RETURN,它是否会执行CATCH?+1 SQL Server 2000,因此这无助于回答我的问题。但对于试图处理异常的人来说,这是一种有用的技术,我真的很喜欢这样。但是叹息。。。还有一些新的东西需要学习。当然,你不应该在没有指定列的情况下编写插入代码。当然,我想在没有指定列的情况下编写插入代码。现在我必须指定它们,添加到源表的其他列将丢失。这似乎是一种更干净/更快的方式来键入。