Précédent   Forum des professionnels en informatique > Bases de données > Oracle > SQL
SQL Forum d'entraide sur le SQL pour Oracle
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 04/04/2011, 09h31   #1
Invité de passage
 
Céline
Inscription : février 2011
Messages : 14
Détails du profil
Informations personnelles :
Nom : Céline

Informations forums :
Inscription : février 2011
Messages : 14
Points : 0
Points : 0
Par défaut boucle dans INSERT

bonjour,

je travaille avec SQL developper.
Je fais de l'appariement de libellé de voie.
Je cherche à insérer dans une table RECAP, les données d'une autre table (table A), tout en leur affectaant un niveau d'appariement..

Niv 0: libelle identique entre les deux tables
Niv1 : type de voie et mot classant identiques...
Niv 2: type de voies différents et mot classants identiques.
Niv 3 : absence de voies

Le problème se pose au niv 2. les données s'apparient bien mais il me reste des libellés qu'il ne m'a pas trouvé.

Par exemple,
Dans la TABLE A, j'ai AVENUE TOURNESOLS, BOULEVARD TOURNESOLS et TRAVERSE DES TOURNESOLS.
Dans ma table RECAP, j'ai AVENUE DES TOURNESOLS et BOULEVARD DES TOURNESOLS.

Il m'identifie bien AVENUE TOURNESOLS et AVENUE DES TOURNESOLS en niv 1.
Meme chose pour les Boulevard.

Cependant, il ne m'a pas identifier TRAVERSE DES TOURNESOLS en niveau 2. Il me le considère comme une absence de voie (niv 3). Cette voie n'est pas absente mais mal appariée.

Je cherche alors à créer une boucle dans un INSERT.

Objectif : Insérer les voies présentes dans la table A et pas dans la table RECAP,dans la table RECAP qui répondent au critères du niveau 2.
que la boucle tourne jusqu'à qu'elle n'est plus trouvée de voie correspondant au niv2.

Débutante depuis peu avec Oracle et le SQL. Je ne sais pas du tout comment m'y prendre.

Je pensais utiliser une boucle WHILE, vu que je veux que la boucle réponde aux conditions type de voie différents et mot_classants identiques.

Quelqu'un a t-il déjà eu ce type de problème et me donner quelques conseils ???

Merci d'avance
C_line83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/04/2011, 11h02   #2
Membre Expert
 
Avatar de Garuda
 
Homme Philippe CHIRCOP
Chef de projet
Inscription : juin 2007
Messages : 1 109
Détails du profil
Informations personnelles :
Nom : Homme Philippe CHIRCOP
Localisation : France

Informations professionnelles :
Activité : Chef de projet
Secteur : Bâtiment

Informations forums :
Inscription : juin 2007
Messages : 1 109
Points : 1 559
Points : 1 559
Pour t'aider, il faudrait en savoir un peu plus.
Que veux-dire "MOT CLASSANT" ?
IL faudrait également la description de tes tables avec les clés primaire et les relations entre tables !
A première vue, pas besoin de boucle.
Du simple SQL devrait suffire.
__________________
Garuda गरूड
Brahmâ la Guerre et Vishnu la Paix

Oracle 10.2.0.4 - Forms6i patch 17 - Toad 11.1 - sharePoint 2010
Garuda est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/04/2011, 12h24   #3
Invité de passage
 
Céline
Inscription : février 2011
Messages : 14
Détails du profil
Informations personnelles :
Nom : Céline

Informations forums :
Inscription : février 2011
Messages : 14
Points : 0
Points : 0
Mot classant est le dernier mot du libellé.
J'ai 3 tables.
Table H : avec des libellés d'une commune A
Table S : avec les libellés de la même commune.
RECAP table de réception des tables H et S

Je cherche à apparier ces 2 tables en affectant des niveaux d'appariement.

J'ai déjà inséré les données de ma 1ère table adresse(table H).
Je souhaite apparier les données de ma table S avec les données de la table H dans la table RECAP.

TABLE_H
---------

PID_H varchar2
type_voie_h varchar2
libelle_h (nom complet) varchar2
mot_classant_h varchar2


TABLE_S
---------

PID_s varchar2
type_voie varchar2
com_nme varchar2
libelle (nom complet) varchar2
mot_classant varchar2


RECAP
-------
PID_H varchar2
PID_S varchar2
type_voie_h varchar2
type_voievarchar2
libelle_h (nom complet) varchar2
com_nme varchar2
mot_classant_h varchar2
mot_classant varchar2
niv_app_h_s (niv 0,1,2,3) integer

1/ insertion de la table H dans RECAP.
2/ appariement de la table H et S dans RECAP, avec des update de S dans RECAP.

EN gros je veux faire une boucle pour être sûr que tous les libellés de ma table S vont être dans ma table RECAP.

Ce qui n'était pas le cas quand je fais un update pour chaque niveau.

Par exemple,pour le niveau 1 voici le Code:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
UPDATE RECAP SET 
(PID_S,TYPE_VOIE_S,LIBELLE_VOIE_S,MOT_CLASSANT_S,niv_app_h_s,campagne) 
 =(SELECT PID,type_voie,COM_NME,mot_classant,1,campagne FROM table_S
    WHERE TYPE_VOIE=TYPE_VOIE_H
    AND MOT_Classant=MOT_Classant_H
    AND table_S.INSEE=RECAP.INSEE AND rownum =1) 
 
WHERE  
    niv_app_h_s IS NULL AND EXISTS 
(SELECT * FROM Table_s
    WHERE TYPE_VOIE=TYPE_VOIE_H
    AND MOT_Classant=mot_Classant_H 
    AND table_s.INSEE=RECAP.INSEE 
    AND ROWNUM=1
    );
ce code marche parfaitement mais quand je l'applique pour mon niveau 2 avec ma condition type_voie <> type_voie_h et mot_classant=mot_classant_h.
Il y a des voies de S qui ne m'insère pas dans RECAP.
Par exemple dans RECAP,
TYPE_VOIE_H | LIBELLE_H | MOT_CLASSANT_H |
------------------------------------------------------------------------
AVENUE | AVENUE COMMANDANT BERNARD | BERNARD

TYPE_VOIE_S | LIBELLE_S | MOT_CLASSANT_S | Niveau appariement
------------------------------------------------------------------------
IMPASSE IMPASSE BERNARD BERNARD 2



Mais si j'ai en plus dans Table S : TRAVERSE BERNARD.
Moi ce que j'attends c'est :

TYPE_VOIE_H | LIBELLE_H | MOT_CLASSANT_H |
------------------------------------------------------------------------
AVENUE | AVENUE COMMANDANT BERNARD | BERNARD

TYPE_VOIE_S | LIBELLE_S | MOT_CLASSANT_S | Niveau appariement
------------------------------------------------------------------------
TRAVERSE TRAVERSE BERNARD BERNARD 2

ce n'est pas ce qui se passe.
Il considère TRAVERSE BERNARD comme Absente de la table H alors que le niveau 2 existe.

Suite à ce constat, je souhaite faire une boucle pour tout récupérer.

Voilà ce que j'ai tenté :
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
25
26
DECLARE
 
CURSOR C_Niv2 IS
SELECT pid
FROM table_s
WHERE pid NOT IN (SELECT pid_s
                        FROM recap);
 
 
begin
 
FOR c IN C_Niv2
 
Loop
 
exit when c_Niv2%NOTFOUND;
UPDATE RECAP
SET(PID_S,TYPE_VOIE_S,LIBELLE_VOIE_S,MOT_classant_S,niv_app_h_s,campagne) 
 =(SELECT PID,type_voie,COM_NME,mot_classant,2,campagne 
    FROM table_s
 
WHERE type_voie<> type_voie_s
AND mot_directeur_s=mot_directeur_s);
end loop;
close C_Niv2;
end;
et j'ai cette erreur :
Error report:
ORA-01001: curseur non valide
ORA-06512: à ligne 25
01001. 00000 - "invalid cursor" !!

Pouvez m'orienter afin que je puisse comprendre comment faire une boucle dans mon cas? Merci
C_line83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/04/2011, 14h21   #4
Membre Expert
 
Avatar de Garuda
 
Homme Philippe CHIRCOP
Chef de projet
Inscription : juin 2007
Messages : 1 109
Détails du profil
Informations personnelles :
Nom : Homme Philippe CHIRCOP
Localisation : France

Informations professionnelles :
Activité : Chef de projet
Secteur : Bâtiment

Informations forums :
Inscription : juin 2007
Messages : 1 109
Points : 1 559
Points : 1 559
Deja :
Ne pas faire
  • Open cursor
  • Exit when not found
  • Close cursor

car ces trois opérations sont IMPLICITES par l'utilisation de la boucle
FOR curseur IN....
L'erreur vient du fait que vous faites un CLOSE déjà fermé (par la sortie de la boucle)
Code :
1
2
3
4
5
6
7
8
9
10
11
12
DECLARE  
 CURSOR C_Niv2 IS SELECT pid FROM table_s 
WHERE pid NOT IN (SELECT pid_s FROM recap);
begin   
FOR c IN C_Niv2 Loop   
UPDATE RECAP SET(PID_S,TYPE_VOIE_S,LIBELLE_VOIE_S,MOT_classant_S,niv_app_h_s,campagne)   =(SELECT PID,type_voie,COM_NME,mot_classant,2,campagne
      FROM table_s
      WHERE type_voie<> type_voie_s 
      AND mot_directeur_s=mot_directeur_s); 
end loop;
end;
__________________
Garuda गरूड
Brahmâ la Guerre et Vishnu la Paix

Oracle 10.2.0.4 - Forms6i patch 17 - Toad 11.1 - sharePoint 2010
Garuda est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/04/2011, 15h31   #5
Invité de passage
 
Céline
Inscription : février 2011
Messages : 14
Détails du profil
Informations personnelles :
Nom : Céline

Informations forums :
Inscription : février 2011
Messages : 14
Points : 0
Points : 0
je viens de lancer le script !
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
DECLARE   
CURSOR C_Niv2 IS SELECT pid FROM sdis_2010_t1 WHERE pid NOT IN (SELECT pid_s                       
                                                                            FROM recap_test);                           
begin   
FOR c IN 1..2
Loop   
UPDATE RECAP_test SET(PID_S,TYPE_VOIE_S,LIBELLE_VOIE_S,MOT_directeur_S,niv_app_h_s,campagne)   
=(SELECT PID,type_voie,COM_NME,mot_directeur,2,campagne     
        FROM sdis_2010_t1    
        WHERE type_voie<> type_voie_s 
        AND mot_directeur_s=mot_directeur_s); 
end loop;  
end;
et cela me donne une erreur

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Error starting at line 1 IN command:
DECLARE   
CURSOR C_Niv2 IS SELECT pid FROM sdis_2010_t1 WHERE pid NOT IN (SELECT pid_s                       
                                                                            FROM recap_test);                           
begin   
FOR c IN 1..2
Loop   
DBMS_OUTPUT.PUT_LINE( c );
UPDATE RECAP_test SET(PID_S,TYPE_VOIE_S,LIBELLE_VOIE_S,MOT_directeur_S,niv_app_h_s,campagne)   
=(SELECT PID,type_voie,COM_NME,mot_directeur,2,campagne     
        FROM sdis_2010_t1    
        WHERE type_voie<> type_voie_s 
        AND mot_directeur_s=mot_directeur_s); 
end loop;  
end;
Error report:
ORA-01427: sous-interrogation ramenant un enregistrement de plus d'une ligne
ORA-06512: à ligne 8
01427. 00000 -  "single-row subquery returns more than one row"
*Cause:    
*Action:
je me suis surement loupée quelque part !!
j'ai du louper quelquechose mais je ne vois pas trop !!
C_line83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/04/2011, 17h20   #6
Membre Expert
 
Avatar de Garuda
 
Homme Philippe CHIRCOP
Chef de projet
Inscription : juin 2007
Messages : 1 109
Détails du profil
Informations personnelles :
Nom : Homme Philippe CHIRCOP
Localisation : France

Informations professionnelles :
Activité : Chef de projet
Secteur : Bâtiment

Informations forums :
Inscription : juin 2007
Messages : 1 109
Points : 1 559
Points : 1 559
Il faut mettre des alias ou préfixer les colonnes pour discerner le colonnes de même nom dans chacune des tables
Code :
1
2
UPDATE RECAP_test SET(PID_S,TYPE_VOIE_S,LIBELLE_VOIE_S,MOT_directeur_S,niv_app_h_s,campagne)    =(SELECT PID,type_voie,COM_NME,mot_directeur,2,campagne              FROM sdis_2010_t1             WHERE type_voie<> type_voie_s          AND RECAP.mot_directeur_s=sdis_2010_T1.mot_directeur_s)
Sinon mot_directeur_s=mot_directeur_s est TOUJOURS VRAI et raméne donc plus d'une ligne !!!!!
__________________
Garuda गरूड
Brahmâ la Guerre et Vishnu la Paix

Oracle 10.2.0.4 - Forms6i patch 17 - Toad 11.1 - sharePoint 2010
Garuda est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/04/2011, 14h35   #7
Invité de passage
 
Céline
Inscription : février 2011
Messages : 14
Détails du profil
Informations personnelles :
Nom : Céline

Informations forums :
Inscription : février 2011
Messages : 14
Points : 0
Points : 0
re bonjour,

Désolé pour l'absence de réponse...

J'ai bien noté votre conseil mais le problème doit venir d'ailleurs...
J'ai essayé une autre solution :
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
25
26
Boucle DECLARE 
CURSOR Niv2 IS 
  SELECT pid_0311,type_voie_s_0311,com_nme_0311, mot_direct_s_0311 FROM sdis_t1_0311 WHERE pid_0311 NOT IN (SELECT pid_s FROM recap_test);      
pid sdis_t1_0311.pid_0311%type;
type_voie sdis_t1_0311.type_voie_s_0311%type;
com_nme sdis_t1_0311.com_nme_0311%type;
mot_directeur sdis_t1_0311.MOT_DIRECT_S_0311%type;
  SELECT pid_h,type_voie_h,libelle_voie_h, mot_directeur_h FROM recap_test;  
pid_h recap_test.PID_H%type;
type_voie_h recap_test.type_voie_h%type;
libelle_voie_h recap_test.LIBELLE_VOIE_H%type;
mot_directeur_h recap_test.MOT_DIRECTEUR_h%type;
begin   
open niv2;
FOR c IN 1..3
Loop 
FETCH Niv2 INTO type_voie, mot_directeur ;
DBMS_OUTPUT.PUT_LINE( c );
UPDATE RECAP_test SET(PID_S,TYPE_VOIE_S,LIBELLE_VOIE_S,MOT_directeur_S,niv_app_h_s,campagne)   
=(SELECT PID_0311,type_voie_s_0311,COM_NME_0311,mot_direct_s_0311,2,campagne_s_0311     
        FROM  sdis_t1_0311   
        WHERE type_voie_s_0311<> type_voie_h 
        AND MOT_DIRECt_s_0311=MOT_DIRECTEUR_h); 
end loop;  
close Niv2;
end;
J'ai visiblement plus les problème d'avant.

cependant, il m'affiche toujours des erreurs.
Il me dit que "Niv2" n'est pas déclaré alors que j'ai déclaré mon curseur ...
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Error report:
ORA-06550: Ligne 2, colonne 6 :
PLS-00201: l'identificateur 'NIV2' doit être déclaré
ORA-06550: Ligne 2, colonne 1 :
PL/SQL: SQL Statement ignored
ORA-06550: Ligne 5, colonne 7 :
PLS-00201: l'identificateur 'NIV2' doit être déclaré
ORA-06550: Ligne 5, colonne 1 :
PL/SQL: SQL Statement ignored
ORA-06550: Ligne 13, colonne 7 :
PLS-00201: l'identificateur 'NIV2' doit être déclaré
ORA-06550: Ligne 13, colonne 1 :
PL/SQL: SQL Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:
Je comprends pas trop où se trouve mon erreur...
Merci d'avance
C_line83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/04/2011, 09h46   #8
Membre Expert
 
Avatar de Garuda
 
Homme Philippe CHIRCOP
Chef de projet
Inscription : juin 2007
Messages : 1 109
Détails du profil
Informations personnelles :
Nom : Homme Philippe CHIRCOP
Localisation : France

Informations professionnelles :
Activité : Chef de projet
Secteur : Bâtiment

Informations forums :
Inscription : juin 2007
Messages : 1 109
Points : 1 559
Points : 1 559
1) Il y a un select dans la partie DECLARE
2) A quoi sert NIV2 ? Il n'est utilisé nulle part !

Il serait plus simple de nous dire ce que doit faire ce code, car, en l'état, il est, comment dire ... au choix
- peu orthodoxe
- incompréhensible
- compliqué
- illisible
Exemple (trivial) d'utilisation trés courante de boucle "curseur" (trivial parce que dans, l'exemple, on n'aurait même pas besoin de boucle PL/SQ, un simple update suffirait)
Code :
1
2
3
4
5
6
7
8
9
DECLARE
CURSOR cur is SELECT a,b,c FROM table1;
BEGIN
  FOR rec IN cur LOOP
     UPDATE table2 SET col3=rec.c
     WHERE table2.col1=rec.a and table2.col2=rec.b;
  END LOOP;
END;
__________________
Garuda गरूड
Brahmâ la Guerre et Vishnu la Paix

Oracle 10.2.0.4 - Forms6i patch 17 - Toad 11.1 - sharePoint 2010
Garuda est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 01h46.


 
 
 
 
Partenaires

Hébergement Web