Ответ 1
Оператор CONTINUE
- это новая функция в 11g.
Вот связанный с этим вопрос: ключевое слово CONTINUE в Oracle 10g PL/SQL
У меня есть выборка, выполняемая внутри цикла. Если эта выборка не удалась (без данных), я хотел бы 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;
Оператор CONTINUE
- это новая функция в 11g.
Вот связанный с этим вопрос: ключевое слово CONTINUE в Oracle 10g PL/SQL
В предоставленной конструкции вы не нуждаетесь в CONTINUE. После обработки исключения выполняется инструкция после END, если ваш блок EXCEPTION не завершает процедуру. Другими словами, он будет продолжаться до следующей итерации цикла user_rec.
Вам также нужно ВЫБРАТЬ В переменную внутри блока BEGIN:
SELECT attr INTO v_attr FROM attribute_table...
Очевидно, вы также должны объявить v_attr...
Как насчет инструкции 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 в конце цикла, конечно. Нуль может быть заменен, возможно, или может быть возможно приращение счетчика, возможно, до вас.
В этом примере вам действительно нужно просто использовать внешнее соединение.
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;
Обратите внимание, что вы можете использовать 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;