Oracle PL/SQL — выйти из начального конечного блока, если условие не выполнено

Можно ли выйти/пропустить блок begin end, если условие не выполнено?

Пример:

DECLARE
    my_var BOOLEAN := TRUE;

BEGIN
    IF my_var THEN
        EXIT_BEGIN_END_HERE;  -- Exits the block but continue execution after it!
    END IF;

    -- Other stuff happens here. Won't be executed if IF above is true
    INSERT INTO asdf
    VALUES ('asdf', 'asdf');
END;

-- Other stuff happens here

person user5507535    schedule 21.11.2020    source источник


Ответы (3)


Используйте GOTO с меткой:

BEGIN
  DECLARE
    my_var BOOLEAN := TRUE;
  BEGIN
    IF my_var THEN
      GOTO skip_insert;
    END IF;

    -- Other stuff happens here. Won't be executed if IF above is true
    DBMS_OUTPUT.PUT_LINE( 'This should be skipped' );
  END;
  <<skip_insert>>
    DBMS_OUTPUT.PUT_LINE( 'Continue from here.' );
END;
/

Или используйте IF ... THEN ... ELSE ... END IF:

DECLARE
  my_var BOOLEAN := TRUE;
BEGIN
  IF my_var THEN
    NULL
  ELSE
    -- Other stuff happens here. Won't be executed if IF above is true
    DBMS_OUTPUT.PUT_LINE( 'This should be skipped' );
  END IF;

  DBMS_OUTPUT.PUT_LINE( 'Continue from here.' );
END;
/

Которые оба выводят:

Continue from here.

db‹›fiddle здесь

person MT0    schedule 21.11.2020

Я думаю, что следующий пример — лучший пример (и решение), иллюстрирующий то, чего вы пытаетесь достичь.

DECLARE
    my_var BOOLEAN := TRUE;
BEGIN
    BEGIN
        IF my_var THEN
            RAISE PROGRAM_ERROR;
        END IF;
        -- Other stuff happens here. Won't be executed if IF above is true
        DBMS_OUTPUT.PUT_LINE('Not here!');
    EXCEPTION
        WHEN OTHERS THEN
            NULL;
    END;
    -- Other stuff happens here
    DBMS_OUTPUT.PUT_LINE('Continuing.');
END;

Вы хотите выйти только из внутреннего НАЧАЛА-КОНЦА, верно? Таким образом, вы можете использовать RAISE.
Если вы запустите приведенный выше код, он отобразит Continuing.

person Abra    schedule 21.11.2020
comment
вы должны поймать только конкретное исключение, которое вы вызываете. - person Erich Kitzmueller; 21.11.2020
comment
Вызов исключения происходит при возникновении ошибки; это оставляет плохой запах кода, поскольку в коде OP не произошло ничего плохого, и это злоупотребление исключениями для отклонения потока программы. Да, это сработает, но я бы возражал против использования этого метода, если бы выполнял проверку кода (особенно если вы перехватывали OTHERS, а не определяемое пользователем исключение). - person MT0; 21.11.2020

Если кто-то хочет выйти из самого внешнего блока, можно использовать RETURN:

DECLARE
    my_var BOOLEAN := TRUE;

BEGIN
    IF my_var THEN
        RETURN;  -- Exits the block but continue execution after it!
    END IF;

    -- Other stuff happens here. Won't be executed if IF above is true
    INSERT INTO asdf
    VALUES ('asdf', 'asdf');
END;

-- Other stuff happens here

Обратите внимание, что, как указано @MT0, поскольку это выходит из самого внешнего блока, нижеприведенный ниже INSERT INTO asdf не будет выполнен:

DECLARE
    my_var BOOLEAN := TRUE;

BEGIN
    BEGIN
        IF my_var THEN
            RETURN;  -- Exits the outermost block but continue execution after it!
        END IF;

        INSERT INTO qwerty
        VALUES ('qwerty', 'qwerty');
    END;

    -- Other stuff happens here. Won't be executed if IF above is true
    INSERT INTO asdf
    VALUES ('asdf', 'asdf');
END;

-- Other stuff happens here

RETURN также можно использовать внутри процедур.

См. аналогичный вопрос: Прервать программу PL/SQL

person user5507535    schedule 21.11.2020
comment
Это не продолжает выполнение после текущего вложенного блока PL/SQL; он завершает самый внешний блок db‹›fiddle - person MT0; 21.11.2020
comment
@MT0 Спасибо. Я обновлю ответ этой информацией! - person user5507535; 21.11.2020