J'ai un fetch en cours d'exécution dans une boucle. Si cette extraction échoue (pas de données), je voudrais CONTINUE
la boucle du prochain enregistrement à partir de EXCEPTION
.
Est-ce possible?
Je reçois un 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;
L'instruction CONTINUE
est une nouvelle fonctionnalité de 11g.
Voici une question connexe: Mot clé 'CONTINUE' dans Oracle 10g PL/SQL
Dans la construction que vous avez fournie, vous n'avez pas besoin de CONTINUER. Une fois que l'exception est gérée, l'instruction après la fin est exécutée, en supposant que votre bloc EXCEPTION ne termine pas la procédure. En d'autres termes, il continuera à la prochaine itération de la boucle user_rec.
Vous devez également sélectionner SELECT INTO dans une variable de votre bloc BEGIN:
SELECT attr INTO v_attr FROM attribute_table...
Évidemment, vous devez également déclarer v_attr ...
Que diriez-vous de la déclaration ole goto (je sais, je sais, mais cela fonctionne très bien ici;)
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;
Il suffit de mettre end_loop en fin de cycle bien sûr. La valeur null peut être remplacée par un commit ou un incrément de compteur, à vous de décider.
Notez que vous pouvez utiliser WHEN exception THEN NULL
de la même manière que vous utiliseriez WHEN exception THEN continue
. Exemple:
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;
Pour cet exemple, vous devriez simplement utiliser une jointure externe.
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;