2011-05-05 14 views
15

Tengo un fetch ejecutándose dentro de un bucle. Si esta búsqueda falla (sin datos) me gustaría CONTINUE el bucle para el siguiente registro desde el EXCEPTION.¿Es posible CONTINUAR un bucle desde una excepción?

¿Esto es posible?

estoy 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; 
+1

La instrucción 'CONTINUE' es una nueva característica en 11g. ¿Estás seguro de que estás ejecutando esa versión? – angus

+0

Por cierto, mira aquí: http://stackoverflow.com/questions/177752/continue-keyword-in-oracle-10g-pl-sql – angus

+1

@angus - Estamos en 10g, fastidio. Supongo que usaré un 'NULL;' y un montón de instrucciones IF condicionales para ayudar con el ciclo. Publique su respuesta como respuesta y la marcaré como la respuesta correcta. – ProfessionalAmateur

Respuesta

9

En el constructo que nos ha proporcionado, no es necesario un continuar. Una vez que se maneja la excepción, se ejecuta la instrucción después de END, suponiendo que su bloque EXCEPTION no finaliza el procedimiento. En otras palabras, continuará en la siguiente iteración del bucle user_rec.

También necesidad de seleccionar en una variable dentro de su bloque BEGIN:

SELECT attr INTO v_attr FROM attribute_table... 

Obviamente debe declarar v_attr así ...

+0

Gracias, hice un ejemplo rápido y sucio, tienes razón al seleccionar una variable. – ProfessionalAmateur

+0

@ProAm: pensé que podría ser el caso, pero por las dudas ... – DCookie

5

¿Qué hay de la declaración ole Goto (lo sé, lo sé, pero funciona muy bien aquí;)

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; 

Sólo hay que poner end_loop al final de loop por supuesto. El nulo puede ser sustituido con un commit tal vez o un incremento de contador tal vez, depende de ti.

0

Para este ejemplo, realmente debería usar una unión externa.

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

aviso Puede utilizar WHEN exception THEN NULL de la misma manera como lo haría con WHEN exception THEN continue. Ejemplo:

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; 
Cuestiones relacionadas