SQL Server 2000: Как выйти из хранимой процедуры?


как я могу выйти в середине хранимой процедуры?

у меня есть хранимая процедура, где я хочу выручить рано (при попытке отладить его). Я пробовал звонить 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 55

7 ответов:

можно использовать RETURN немедленно остановить выполнение хранимой процедуры. Цитата взята из Книги Онлайн:

безусловный выход из запроса или процедура. Возвращение немедленно и полный и может быть использовано в любой момент для выхода из процедуры, пакета или блок операторов. Заявления о том, что последующие возвраты не выполняются.

из паранойи я попробовал yor пример, и он выводит отпечатки и останавливает выполнение немедленно.

если вы не укажете серьезность 20 или выше,raiserror не остановит выполнение. Смотрите Примечание.

обычный обходной путь должен включать return после raiserror:

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

положите его в TRY/CATCH.

если инструкция raiserror с уровнем серьезности из 11 или выше в блоке TRY, это управления трансферты, связанные Поймать блок

ссылки: MSDN.

EDIT: это работает для MSSQL 2005+, но я вижу, что теперь вы уточнили, что вы работаете на MSSQL 2000. Я оставлю это здесь для справки.

я понял, почему RETURN не является безусловным возвратом из хранимой процедуры. Ошибка, которую я вижу, заключается в том, что хранимая процедура compiled - не тогда, когда она выполняется.

рассмотрим воображаемую хранимую процедуру:

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

несмотря на то, что этот stord proedure содержит ошибку (возможно, это связано с тем, что объекты имеют разное количество столбцов, возможно, в таблице есть столбец timestamp, возможно, хранимая процедура не имеет существуют), вы все еще можете сохранить его. Вы можете сохранить его, потому что вы ссылаетесь на связанном сервере.

но когда вы на самом деле выполнить хранимая процедура, SQL Server затем составляет он и генерирует план запроса.

моя ошибка не происходит на линии 114, это on строка 114. SQL Server не может скомпилировать хранимую процедуру, поэтому она не работает.

и поэтому 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

Это кажется много кода, но лучший способ я нашел, чтобы сделать это.

    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

Это потому что у вас нет BEGIN и END заявления. Вы не должны видеть отпечатки или ошибки при выполнении этого оператора, только Statement Completed (или что-то в этом роде).