Oracle
 sql >> Base de données >  >> RDS >> Oracle

oracle execute immediate ne s'exécutant pas sans aucune erreur

La raison pour laquelle votre code ne fait rien est la suivante :

OPEN c1;
 LOOP
  EXIT WHEN c1%NOTFOUND;   
  EXIT WHEN (c1%ROWCOUNT <> p_SCBCount);

Vous testez c1%ROWCOUNT avant d'avoir exécuté une récupération. Sa valeur est donc 0 ; Je devine p_SCBCount n'est pas nul à ce stade (parce que vous l'avez initialisé à une valeur dans le bloc DECLARE) afin que test soit évalué à true et que le programme se termine.

Sinon, le problème est le suivant :

OPEN c1;
 LOOP
   ...
   FOR i in c1 LOOP

Nous ne pouvons pas utiliser le FOR ... IN avec un curseur explicite. Vous avez ouvert le curseur. Puis le FOR essaie de l'ouvrir à nouveau, ce qui lance ORA-06511: PL/SQL: cursor already open . Si vous ne voyez pas cette erreur, vous devez avoir un gestionnaire d'exception qui la supprime (par exemple WHEN others then null; ).

Fondamentalement, la boucle externe est complètement inutile et vous devez la jeter.

Le contrôle de boucle explicite est rarement nécessaire :utilisez simplement le FOR ... IN construire et laisser Oracle contrôler le flux.

Tout le SQL dynamique est également inutile. SQL fonctionne avec des variables, il vous suffit donc d'écrire du SQL statique qui fait référence aux attributs du curseur :

 FOR i in (SELECT crs_cust.CUSTOMER_ID AS CUSTOMER_ID
                 , subset.NEW_CUSTOMER_REFERENCE_ID AS CUSTOMER_REF_ID 
           FROM CRS_CUSTOMERS crs_cust 
           INNER JOIN  DAY0_SUBSET subset
           ON crs_cust.CUSTOMER_ID=subset.CURRENT_CUSTOMER_ID )
 LOOP
     UPDATE CRS_CUSTOMERS 
     SET REF_ID = i.CUSTOMER_REF_ID
     WHERE CUSTOMER_ID = i.CUSTOMER_ID; 
     p_TotalUpdatedCRS := p_TotalUpdatedCRS + 1;

     UPDATE CRS_REVIEWS
     SET REF_ID =  i.CUSTOMER_REF_ID
     WHERE CUSTOMER_ID =  i.CUSTOMER_ID; 

     UPDATE CRS_EVENT 
     SET REF_ID = i.CUSTOMER_REF_ID 
     WHERE UNIQUE_ID = i.CUSTOMER_ID;

     UPDATE ALERT_HEADER 
     SET CUSTOMER_SOURCE_REF_ID = i.CUSTOMER_REF_ID 
     WHERE CUSTOMER_ID = i.CUSTOMER_ID; 
END LOOP;
DBMS_OUTPUT.PUT_LINE ('The total updates to CRS table = ' || p_TotalUpdatedCRS); 

Je ne suis pas sûr du but de c1%ROWCOUNT <> p_SCBCount . Mon intuition est que c'est superflu, car la FOR LOOP contrôle les récupérations avec précision. En fait, je soupçonne que vous l'avez ajouté pour éviter les effets secondaires des boucles imbriquées ; et je soupçonne que vous n'avez introduit les boucles imbriquées que parce que votre code d'origine a lancé PLS-00376: illegal EXIT/CONTINUE statement; it must appear inside a loop (juste une supposition sauvage).

Cependant, si cela sert à implémenter une véritable logique métier, vous pouvez l'ajouter d'une manière ou d'une autre dans la boucle.