IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PL/SQL Oracle Discussion :

Curseur & violation de contrainte & poursuite du traitement


Sujet :

PL/SQL Oracle

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 81
    Points : 51
    Points
    51
    Par défaut Curseur & violation de contrainte & poursuite du traitement
    bonjour,

    J'essaye d'insérer des lignes dans une table munie d'une contrainte d'intégrité.
    Lorsque les lignes existent déjà, l'insertion plante (très bien).
    Mais lorsque j'essaye d'insérer des lignes de manière répétitive avec un curseur dans un bloc de code, l'exécution s'arrête au premier échec d'insertion.

    Comment gérer cette exception et poursuivre l'exécution à la valeur suivante du curseur ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    DECLARE
    CURSOR c_sect IS
    SELECT id_secteur FROM t_secteur;
    BEGIN
      FOR c IN c_sect LOOP
        dbms_output.put_line( To_char( c.id_secteur ) ) ;
        INSERT INTO t_user (id_secteur,id_agent)
        SELECT c.id_secteur,id_agent
        FROM agent
        WHERE id_agent IN('toto','tata') ;
      END LOOP ;
    EXCEPTION
       WHEN DUP_VAL_ON_INDEX
       THEN ROLLBACK;
    END ;
    /
    Evidemment, une solution plus propre consisterait à faire une bonne sélection
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        SELECT c.id_secteur,id_agent
        FROM agent
        WHERE id_agent IN('toto','tata')
        AND NOT EXISTS(
          SELECT id_secteur,id_agent
          FROM t_user
          WHERE id_secteur=c.id_secteur
          AND id_agent IN('toto','tata')
          )
        );
    Mais je me pose la question de la gestion de l'exception
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    EXCEPTION
       WHEN DUP_VAL_ON_INDEX
       THEN ?? ;
    des possibilités et moyens d'arrêter ou poursuivre un curseur

    Merci d'avance

  2. #2
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Points : 1 359
    Points
    1 359
    Par défaut
    Bonjour,

    Vous pouvez:

    (a) soit encapsuler votre traitement de LOOP dans un BEGIN/EXCEPTION/END bloc afin que chaque itération en erreur soit retenue dans l'exception de ce bloc; par contre prenez soin de bien gérer les exceptions dans ce cas. En effet il faut que vous vous posiez la question essentielle qui est de savoir quoi faire avec les insertions en erreur dans ce cas.

    (b) soit, si vous êtes sur une version 10g ou plus, d'utiliser le "DML error logging" dont vous trouverez des exemples partout sur internet. Si vous optez pour cette solution pensez alors dans ce cas à lire ce simple article que j'ai écris sur les restrictions du DML error logging
    Bien Respectueusement
    www.hourim.wordpress.com

    "Ce qui se conçoit bien s'énonce clairement"

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    J'ajouterai qu'une simple jointure annule aussi l'intérêt du curseur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    INSERT INTO t_user (id_secteur, id_agent)
    SELECT sec.id_secteur
         , agn.id_agent
      FROM agent agn
           CROSS JOIN t_secteur sec
           LEFT OUTER JOIN t_user usr
             ON usr.id_secteur = sec.id_secteur
            AND usr.id_agent   = agn.id_agent
     WHERE agn.id_agent IN ('toto','tata')
       AND usr.id_user IS NULL; -- la PK ou une colonne non nulle de la table t_user

  4. #4
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Ou utilisez ForAll avec Save Exceptions: "Handling FORALL Exceptions After FORALL Statement Completes"

  5. #5
    Membre chevronné
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Février 2012
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Distribution

    Informations forums :
    Inscription : Février 2012
    Messages : 652
    Points : 1 878
    Points
    1 878
    Par défaut
    Comme dis plus haut, il suffit de gérer cette exception au niveau de la boucle

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    DECLARE
    CURSOR c_sect IS
    SELECT id_secteur FROM t_secteur;
    BEGIN
      FOR c IN c_sect LOOP
        BEGIN    
          dbms_output.put_line( To_char( c.id_secteur ) ) ;
          INSERT INTO t_user (id_secteur,id_agent)
          SELECT c.id_secteur,id_agent
          FROM agent
          WHERE id_agent IN('toto','tata') ;
        EXCEPTION
          WHEN DUP_VAL_ON_INDEX THEN
           dbms_output.put_line('DUP_VAL_ON_INDEX : Id secteur '||c.id_secteur||' / Id agent '||c.id_agent);
        END;
      END LOOP ;
    EXCEPTION
       WHEN OTHERS THEN 
         dbms_output.put_line('Erreur globale : '||SQLERRM);
         dbms_output.put_line('Transaction annulée');
         ROLLBACK;
    END ;
    /

Discussions similaires

  1. Faire un ROLLBACK si des erreurs ou violations de contraintes
    Par Smalo dans le forum Développement
    Réponses: 5
    Dernier message: 10/06/2008, 11h08
  2. violation de contrainte unique (KOLOK.IDCONFIG_PK)
    Par Sephiroth Lune dans le forum Administration
    Réponses: 12
    Dernier message: 20/04/2007, 11h51
  3. [hibernate] Violation de contrainte unique
    Par miyabi dans le forum Hibernate
    Réponses: 1
    Dernier message: 07/06/2006, 14h52
  4. [Oracle] Script création Table, violation de contraintes
    Par boudou dans le forum Langage SQL
    Réponses: 2
    Dernier message: 21/02/2006, 13h47
  5. Réponses: 2
    Dernier message: 13/02/2006, 11h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo