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 30/12/2010, 16h58   #1
Invité de passage
 
Inscription : décembre 2010
Messages : 8
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 8
Points : 0
Points : 0
Par défaut Appel d'un curseur sur une table pas encore créée

Bonjour,

le problème est le suivant : j'ai un script PL/SQL qui permet d'alimenter une table depuis une autre. Dans ce script, une procédure crée une table temporaire et l'alimente avec les données sources. Ensuite je dois parcourir cette table pour alimenter la cible (boucle LOOP avec des INSERT). La table temporaire est détruite à la fin du script.

Au lancement du script donc, la table temporaire n'existe pas. Et donc le curseur qui pointe dessus pose problème et j'ai l'erreur TABLE INEXISTANTE au lancement.

J'ai d'abord déclaré le curseur dans le DECLARE. Puis aussi après la procédure avec la syntaxe suivante pour ruser un peu mais le problème est identique :
Code :
1
2
3
FOR record IN (SELECT * FROM TMP_MA_TABLE) LOOP
      INSERT ... ;
   END LOOP;
Si je force la création de la table temporaire au début du script c'est pareil aussi.

Merci d'avance de votre aide si vous avez une idée !
coco_mtl est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/12/2010, 18h22   #2
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
Tu utilises les tables temporaires comme dans SqlServer mais c'est différent sur Oracle, cf asktom sur les tables temporaires.
Citation:
the main exception being that they are 'statically' defined. You create
them once per database, not once per stored procedure in the database.
Il existe sûrement d'autres entrées autour de ce sujet sur asktom.
Sinon concernan l'insert, le curseur semble inutile, il vaut mieux juste un insert :
Code :
1
2
INSERT INTO MA_TABLE
SELECT * FROM TMP_MA_TABLE
Une autre entrée où l'utilisation est plutôt comme une interface :
http://asktom.oracle.com/pls/apex/f?...15826034070548
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/12/2010, 20h59   #3
Membre Expert
 
Avatar de pachot
 
Homme Franck Pachot
DBA Oracle
Inscription : novembre 2007
Messages : 703
Détails du profil
Informations personnelles :
Nom : Homme Franck Pachot
Âge : 41
Localisation : Suisse

Informations professionnelles :
Activité : DBA Oracle
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : novembre 2007
Messages : 703
Points : 1 630
Points : 1 630
Bonjour,
Pour créer une procédure qui utilise une table qui n'existe pas encore, il faut faire du SQL dynamique.
Mais pour une table temporaire, sous Oracle, il ne faut pas la créer à chaque fois, mais créer une Global Temporary Table.
Cordialement,
Franck.
__________________
A lire sur mon blog Oracle - Articles d'Experts des articles traduits en français de Jonathan Lewis, Tom Kyte, Doug Burns, Cary Millsap, Greg Rahn ...
pachot est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2010, 09h17   #4
Invité de passage
 
Inscription : décembre 2010
Messages : 8
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 8
Points : 0
Points : 0
Citation:
Envoyé par skuatamad Voir le message
Tu utilises les tables temporaires comme dans SqlServer mais c'est différent sur Oracle, cf asktom sur les tables temporaires.

Il existe sûrement d'autres entrées autour de ce sujet sur asktom.
Sinon concernan l'insert, le curseur semble inutile, il vaut mieux juste un insert :
Code :
1
2
INSERT INTO MA_TABLE
SELECT * FROM TMP_MA_TABLE
Une autre entrée où l'utilisation est plutôt comme une interface :
http://asktom.oracle.com/pls/apex/f?...15826034070548
En fait je me suis mal exprimé : j'utilise une table temporaire mais pas au sens TEMPORARY TABLE. C'est une table classique en fait.

Sinon mon curseur me sert à parcourir les lignes une à une. J'en ai besoin car en cas de rejet d'insertion sur une ligne je récupère certaine infos (ROWID...).
coco_mtl est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2010, 10h18   #5
Invité de passage
 
Inscription : décembre 2010
Messages : 8
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 8
Points : 0
Points : 0
Citation:
Envoyé par pachot Voir le message
Bonjour,
Pour créer une procédure qui utilise une table qui n'existe pas encore, il faut faire du SQL dynamique.
Oui je parviens bien à générer la requête d'insertion mais le problème c'est faire une LOOP pour parcourir chaque enregistrement. Pour l'instant j'ai le code suivant mais je vois pas comment faire une boucle :

Code :
1
2
3
4
5
6
7
 
BEGIN
   DWH.CREATE_TMP ('TMP_TOTO', 'SELECT * FROM ...');
 
   REQ := 'INSERT INTO TOTO (ch1, ch2) (SELECT ch1, ch2 FROM TMP_TOTO)';
   EXECUTE IMMEDIATE REQ;
END;
coco_mtl est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2010, 11h51   #6
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
Il y a pas mal de chose dans la doc notemment si tu veux BULK LOADER : Native Dynamic SQL
voici un exemple :
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
SQL> CREATE TABLE MA_TABLE (a number, b varchar2(10))
  2  /
 
TABLE created.
 
SQL> declare
  2    l_select varchar2 (100);
  3    l_insert varchar2 (100);
  4    l_cursor sys_refcursor;
  5    l_rec  MA_TABLE%rowtype;
  6  begin
  7    execute immediate 'create table TMP_MA_TABLE (a number, b varchar2(10))';
  8    execute immediate 'insert into TMP_MA_TABLE (a, b) values (1,''toto'')';
  9    commit;
 10    l_select := 'select a,b from TMP_MA_TABLE';
 11    open l_cursor FOR l_select;
 12      loop fetch l_cursor INTO l_rec;
 13        exit when l_cursor%notfound;
 14  
 15        l_insert := 'insert into MA_TABLE (a, b) values (:1, :2)';
 16        execute immediate l_insert USING l_rec.a, l_rec.b;
 17      end loop;
 18    close l_cursor;
 19    commit;
 20    execute immediate 'drop table TMP_MA_TABLE';
 21  end;
 22  /
 
PL/SQL procedure successfully completed.
 
SQL> SELECT * FROM ma_table
  2  /
 
         A B
---------- ----------
         1 toto
 
SQL> DROP TABLE ma_table
  2  /
 
TABLE dropped.
Par contre je ne vois tout de même pas l'intérêt de supprimer et recréer la table, autant la conserver.
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 31/12/2010, 14h36   #7
Invité de passage
 
Inscription : décembre 2010
Messages : 8
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 8
Points : 0
Points : 0
Citation:
Envoyé par skuatamad Voir le message
Il y a pas mal de chose dans la doc notemment si tu veux BULK LOADER : Native Dynamic SQL
voici un exemple :

Par contre je ne vois tout de même pas l'intérêt de supprimer et recréer la table, autant la conserver.
Merci ça marche effectivement très bien comme ça !

Quant à la suppression moi non plus je ne vois pas l'intérêt mais je me plie aux normes de devs
coco_mtl est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2011, 10h52   #8
Invité de passage
 
Inscription : décembre 2010
Messages : 8
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 8
Points : 0
Points : 0
Citation:
Envoyé par skuatamad Voir le message
Il y a pas mal de chose dans la doc notemment si tu veux BULK LOADER : Native Dynamic SQL
voici un exemple :
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
SQL> CREATE TABLE MA_TABLE (a number, b varchar2(10))
  2  /
 
TABLE created.
 
SQL> declare
  2    l_select varchar2 (100);
  3    l_insert varchar2 (100);
  4    l_cursor sys_refcursor;
  5    l_rec  MA_TABLE%rowtype;
  6  begin
  7    execute immediate 'create table TMP_MA_TABLE (a number, b varchar2(10))';
  8    execute immediate 'insert into TMP_MA_TABLE (a, b) values (1,''toto'')';
  9    commit;
 10    l_select := 'select a,b from TMP_MA_TABLE';
 11    open l_cursor FOR l_select;
 12      loop fetch l_cursor INTO l_rec;
 13        exit when l_cursor%notfound;
 14  
 15        l_insert := 'insert into MA_TABLE (a, b) values (:1, :2)';
 16        execute immediate l_insert USING l_rec.a, l_rec.b;
 17      end loop;
 18    close l_cursor;
 19    commit;
 20    execute immediate 'drop table TMP_MA_TABLE';
 21  end;
 22  /
 
PL/SQL procedure successfully completed.
 
SQL> SELECT * FROM ma_table
  2  /
 
         A B
---------- ----------
         1 toto
 
SQL> DROP TABLE ma_table
  2  /
 
TABLE dropped.
Je relance le sujet pour une question additionnelle : je dois, en cas de rejet lors de l'insertion de la ligne dans MA_TABLE, lancer une procédure spécifique avec le ROWID de la ligne en question.
Le problème c'est que je parcours le curseur de type MA_TABLE%rowtype. Donc quand je lance la procédure avec en paramètre l_rec.ROWID il ne le connait pas évidemment.
Merci de votre aide.
coco_mtl est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2011, 12h05   #9
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 311
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 311
Points : 5 808
Points : 5 808
Utilisez un curseur modèle pour déclarer le rowid
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
Connected TO Oracle DATABASE 10g Enterprise Edition Release 10.2.0.4.0 
Connected AS mni
 
SQL> 
SQL> declare
  2    cursor crs_modele IS
  3      SELECT rowid, t.*
  4        FROM ma_table t;
  5    --
  6    SubType rMa_Table IS crs_modele%RowType;
  7    l_var   rMa_Table;
  8  Begin
  9    NULL;
 10  End;
 11  /
 
PL/SQL procedure successfully completed
 
SQL>
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2011, 17h17   #10
Invité de passage
 
Inscription : décembre 2010
Messages : 8
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 8
Points : 0
Points : 0
Citation:
Envoyé par mnitu Voir le message
Utilisez un curseur modèle pour déclarer le rowid

Merci beaucoup !
coco_mtl est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 15h47.


 
 
 
 
Partenaires

Hébergement Web