web-dev-qa-db-fra.com

Est-il possible de CONTINUER une boucle d'une exception?

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;
17

L'instruction CONTINUE est une nouvelle fonctionnalité de 11g.

Voici une question connexe: Mot clé 'CONTINUE' dans Oracle 10g PL/SQL

13
angus

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 ...

10
DCookie

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.

6
tbone

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;
0
Tagar

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;
0
bozon