Можно ли ПРОДОЛЖИТЬ цикл из исключения?

У меня есть выборка, выполняемая внутри цикла. Если эта выборка не удалась (без данных), я хотел бы CONTINUE создать цикл для следующей записи из EXCEPTION.

Возможно ли это?

Я получаю ORA-06550 и PLS-00201 identifer CONTINUE must be declared

DECLARE
   v_attr char(88);
CURSOR  SELECT_USERS IS
SELECT id FROM USER_TABLE
WHERE USERTYPE = 'X';
BEGIN
    FOR user_rec IN SELECT_USERS LOOP    
        BEGIN
            SELECT attr INTO v_attr 
            FROM ATTRIBUTE_TABLE
            WHERE user_id = user_rec.id;            
         EXCEPTION
            WHEN NO_DATA_FOUND THEN
               -- user does not have attribute, continue loop to next record.
               CONTINUE;
         END;         
    END LOOP;
END;

Ответы

Ответ 2

В предоставленной конструкции вы не нуждаетесь в CONTINUE. После обработки исключения выполняется инструкция после END, если ваш блок EXCEPTION не завершает процедуру. Другими словами, он будет продолжаться до следующей итерации цикла user_rec.

Вам также нужно ВЫБРАТЬ В переменную внутри блока BEGIN:

SELECT attr INTO v_attr FROM attribute_table...

Очевидно, вы также должны объявить v_attr...

Ответ 3

Как насчет инструкции ole goto (я знаю, я знаю, но он отлично работает здесь;)

DECLARE
   v_attr char(88);
CURSOR  SELECT_USERS IS
SELECT id FROM USER_TABLE
WHERE USERTYPE = 'X';
BEGIN
    FOR user_rec IN SELECT_USERS LOOP    
        BEGIN
            SELECT attr INTO v_attr 
            FROM ATTRIBUTE_TABLE
            WHERE user_id = user_rec.id;            
         EXCEPTION
            WHEN NO_DATA_FOUND THEN
               -- user does not have attribute, continue loop to next record.
               goto end_loop;
         END;

        <<end_loop>>
        null;         
    END LOOP;
END;

Просто поставьте end_loop в конце цикла, конечно. Нуль может быть заменен, возможно, или может быть возможно приращение счетчика, возможно, до вас.

Ответ 4

В этом примере вам действительно нужно просто использовать внешнее соединение.

declare
begin
  FOR attr_rec IN ( 
    select attr 
    from USER_TABLE u 
    left outer join attribute_table a 
    on ( u.USERTYPE = 'X' and a.user_id = u.id ) 
  ) LOOP
    <process records> 
    <if primary key of attribute_table is null 
     then the attribute does not exist for this user.>
  END LOOP;
END;

Ответ 5

Обратите внимание, что вы можете использовать WHEN exception THEN NULL так же, как использовать WHEN exception THEN continue. Пример:

    DECLARE
        extension_already_exists  EXCEPTION;
        PRAGMA EXCEPTION_INIT(extension_already_exists, -20007);
        l_hidden_col_name  varchar2(32);
    BEGIN
        FOR t IN (  SELECT table_name, cast(extension as varchar2(200)) ext
                    FROM all_stat_extensions
                    WHERE owner='{{ prev_schema }}'
                      and droppable='YES'
                    ORDER BY 1
                 )
        LOOP
            BEGIN
                l_hidden_col_name := dbms_stats.create_extended_stats('{{ schema }}', t.table_name, t.ext);
            EXCEPTION
                WHEN extension_already_exists THEN NULL;   -- ignore exception and go to next loop iteration
            END;
        END LOOP;
    END;