Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 10/12/2011, 09h10   #1
Candidat au titre de Membre du Club
 
Inscription : juillet 2003
Messages : 52
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 52
Points : 13
Points : 13
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 :
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 :
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 :
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
carreau est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/12/2011, 11h45   #2
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 562
Points : 562
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
http://hourim.wordpress.com/2011/02/...-restrictions/
__________________
Bien Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2011, 11h48   #3
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 686
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 686
Points : 10 435
Points : 10 435
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
J'ajouterai qu'une simple jointure annule aussi l'intérêt du curseur :
Code :
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
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2011, 14h52   #4
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 313
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 313
Points : 5 817
Points : 5 817
Ou utilisez ForAll avec Save Exceptions: "Handling FORALL Exceptions After FORALL Statement Completes"
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 29/02/2012, 14h36   #5
Membre confirmé
 
Inscription : février 2012
Messages : 203
Détails du profil
Informations forums :
Inscription : février 2012
Messages : 203
Points : 267
Points : 267
Comme dis plus haut, il suffit de gérer cette exception au niveau de la boucle

Code :
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 ;
/
Scriuiw est déconnecté   Envoyer un message privé Réponse avec citation 01
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 22h27.


 
 
 
 
Partenaires

Hébergement Web