Insertion multiple
RésoluPour insérer une ligne dans une table pas de souci :-) mais pour en insérer plusieurs un pb :-(
J'ai pris comme modèle
Insert into Voiture(Annee,Marque,Modèle,Identifiant)
VALUES (1984,Renault,Fuego,3,
2000,Renault,Clio2,4,
2001,Renault,Avensis,5
);
que j'avais trouvé sur http://www.wikituto.org/index.php/Ins%C3%A9rer_des_donn%C3%A9es_SQL
mais j'ai un message d'erreur comme quoi trop de valeurs :-(
qq'un a une idée ?
23 réponses
Le sujet traite de l’insertion simultanée de plusieurs lignes dans une table et des erreurs qui surviennent lorsque le nombre de valeurs ne correspond pas au nombre de colonnes lors d’un INSERT INTO. Des approches courantes privilégient les insertions multiples classiques, mais elles ne sont pas universellement supportées selon le SGBD; d’autres optent pour SQLLoader ou pour charger via un fichier. Concrètement, les échanges évoquent l’usage d’un fichier de contrôle et d’un fichier de données pour SQLLoader, traçabilité des lignes rejetées et triggers PL/SQL pour les contrôles lors de l’insertion. En pratique, certains rappellent que l’ordre d’insertion multiple n’est pas standardisé en SQL pur et proposent des alternatives comme le chargement dans une table temporaire suivie d’un traitement via déclencheurs.
-
Dans le bandeau du forum, à côté de ton pseudo, tu devrais avoir un 1 qui s'affiche par dessus l'enveloppe.
Tu cliques dessus et tu devrais être dans la messagerie interne du forum.
Une lste de mails que tu as reçus (et que tu as envoyés) apparaît à l'écran.
Pour l'utilisation de la messagerie, c'est du classique.
A tout de suite. -
Salut BG
Merci bcp de ta réponse,
Ta proposition, de me laisser ton adresse mail, est très sympa ...
si t'es toujours d'accord, donc dis-moi où je peux récupérer ton adresse,
merci -
Bonsoir CodeForEver,
Je crains que tu te sois trompée dans l'extension du fichier de contrôle : c'est .ctl (je ne sais pas si une autre extension est possible).
et dans la ligne DOS, mets bien les attributs de la commande sqlldr (c'est plus sûr comme méthode) :sqlldr userid=tonLogin/tonMotDePasse@tonSIDBD control=fic_controles.ctl DATA=fic_donnees.txt
Proposition :
Si tu veux, par la messagerie interne de ce forum, je te donnerai mon adresse mail perso. Tu m'enverras alors ton travail concernant le SQLLoader (description de la table, fichier de contrôle, ligne de commande) et j'essaierai de charger les données de mon côté (je suis sûr qu'il y a un petit loup qui nous a échappé).
Qu'en penses-tu de cette proposition ? (si tu es d'accord, je t'envoie mon mail perso par messagerie interne de ce forum et toi en réponse à ce mail, tu m'envoies ton travail)
@+
-
Salut CodeForEver,
Juste un petit post (enfin ... je vais essayer !) pour te dire que j'ai trouvé (j'en suis sûr) le pourquoi de l'impossibilité de mettre tes données à charger dans un fichier externe : c'est à cause de l'option INFILE *.
Le chargement écrit ainsi :LOAD DATA REPLACE INTO TABLE
prendrait alors en compte le fichier désigné par le paramètre DATA de ta ligne de commande :SQLLdr USERID=tonLogin/tonMotDePasse@tonSIDBD CONTROL=fic_controles.ctl DATA=fic_donnees.txt ...
Bon ... je suis un vrai pitbull : tant que j'ai un os à ronger (= un problème informatique non résolu), je continue à chercher ... à la limite, j"en deviendrais casse-pieds ;-)
Mais là, je crois que toutes les facettes du problème ont été vues.
Bonne journée.-
Salut BG,
Merci bcp de ton message, je l'ai lu que là avec bcp de retard ...
Tu sais moi aussi par fois je continue à chercher alors que qq'un de plus "normal" (!!!) aurait oublié le sujet !!!
Du coup je ré-essayé ton code mais toujours les mêmes réponses :-(
dans mon fhicher.clt j'ai :
LOAD DATA REPLACE INTO TABLE matable FILED TERMINED BY ... (col1, col2, ...)
sur le console je mets les lignes
sqlldr monlogin/monpw
entrer
il affichecontrol=
j'y ajout le path de mon fichier.clt
entrer et message d'erreur :-(
et si après le path de fichier.clt j'ajout le path de fichier .dat c'est encore pire ...
en attendant je m'en suis sortie en intégrant les données dans le fichier .clt mais on ne peut pas le faire toujours c'est pourquoi j'aurais aimé trouver la solution pour ça ...
mais avec tout aide et gentillesse que tu m'adresse le problème persiste...
en tout cas on y arrivera ;-)
-
-
Salut CodeForEver,
Ravi de voir que tes efforts (et mes quelques infos) ne sont pas vains.
Et bonne fin de week-end tout de même ,-) -
Salut BadGuitarist,
c'est vrai que mon week-end est studieux !!!
entre deux lignes de java (eh oui java aussi !!!) j'ai donc essayé mon code avec ton idée "REPLACE" ...
ce n'est pas pour te faire plaisir que je dis ça mais effectivement c'est le meilleur ;-)
il ajoute les nouvelles données sans doublonner les anciennes : chouette non ?
qu'il vide la table, ou il remplace les anciens par eux-mêmes c'est son affaire pourvu que le résultat soit bon et c'est le cas ! (au moins avec les exemples divers que j'ai fait).
Par contre je n'ai pas pu voir pour le fichier .bad pour le moment (je le mets sur le dos de java !) dès que je le fait je te fais signe ;-)
bon après midi -
Bonjour CodeForEver,
En effet, il semblerait que tu vas passer un week-end très studieux.
Pour ce qui est du fichier .ctl (mais je n'insiste pas : tu as une solution qui marche ;-), il se peut que dans tes chemins, tes répertoires ont des espaces ... et là, sous windows, ça coince.
Concernant l'option REPLACE, je suis intéressé par le résultat de ton test : car je sais que c'est utilisé pour écrasé le contenu de la table dans laquelle on insère ... mais je crois (mais je ne suis plus sûr) qu'avec cette option, sqlloader vide d'abord la table puis fait les insert.
@+ -
Salut BadGuitarist,
Merci de ta réponse et ta présence ;-)
--------- pour l'histoire de .ctl
Pour charger les données depuis le fichier .dat j'avais essayer tout ce qui est le chemin du fichier, son répertoire (qui est le même que tout les autres fichier, etc)
Finalement après une bonne nuit blanche (comme la neige !!) je me suis persuadée que c'est dû à windows, car je travail sous windows.
un tuto du oracle, pour windows parle que d'intégration des données dans le fichier .clt finalement j'ai fait la paix et je l'ai accepté !!
Et en plus ça marche donc je ne vais pas compliquer !!
Par contre je vais corriger mon code (grâce à un point qui m'a sauté aux yeux grâce à ta note de l'Etape 2).
c'est que ma code est :
LOAD DATA INFILE * APPEND INTO TABLE MACHIN FIELDS TERMINATED....
et bien tu parles de REPLACE ... eh oui c'est ça qu'il faut car quand je refais la même manipe (pour le moment) il double les lignes (à cause de APPEND).
par contre je ne sais pas s'il replace les données existantes et intèger en suite les nouvelles ... je vais essayer ça tout à l'heure.
--------- pour l'histoire de .bad
Merci de ton aide ça aussi je vais essayer tout à l'heure : tu vois que j'ai prévu un super bon week-end !!!
--------- pour l'histoire de PL/SQL
Merci de ton encouragement et ta générosité... donc on en parlera dans les jours qui viennent ;-)
Passe une super belle journée -
Bonjour CodeForEver,
Bien ! ... Félicitations pour ta réussite et pour ta persévérance ;-)
Petite remarque : si tu n'as pas pu charger les données contenues dans un fichier ".txt" (par exemple), c'est peut-être parce que tu n'as pas mentionné le path :C:\ORANTV9\bin\SQLLdr USERID=tonLogin/tonMotDePasse@tonSIDBD CONTROL=c:\tests\insertionMultiple\load_annuaire_SAP.ctl LOG=c:\tests\insertionMultiple\load_annuaire_SAP.log BAD=c:\tests\insertionMultiple\load_annuaire_SAP.bad DATA=c:\tests\insertionMultiple\Z_telecom.txt ERRORS=9999 ROWS=1000
Dans l'exemple que je t'avais donné, je supposais que tu étais positionnée dans le répertoire de travail où se trouvait le fichier à charger.
En ce qui concerne le problème de la récupération des lignes rejetées dans le fichier ".bad",
1- Etape 1 :
- dans ton cas (données intégrées au fichier .ctl),
il te faut copier-coller le contenu du fichier .bad et le mettre dans ton fichier .ctl (si besoin,
tu sauvegardes le fichier de contrôle avant modification pour conserver la trace de tes insertions).
- dans mon cas (données contenues dans un fichier de données),
tu sauvegardes ton fichier de données et tu renommes le fichier .bad avec le même nom que ton fichier
de données (avant renommage ;-)
2- Etape 2 :
Tu relances la commande SQLLOADER
(attention si tu as choisi l'option REPLACE dans ton fichier de contrôle).
Bien sûr, en étape 0, il aura fallu comprendre pourquoi les données ont été rejetées (et donc avoir corrigé le problème; en général, c'est une contrainte du genre colonne non nulle ou longueur max dépassée.
PS. :
pour ce qui est du PL/SQL, tu ne devrais pas avoir beaucoup de problème. Ce n'est pas un langage bien compliqué. Mais, si besoin, j'essaierai de répondre à tes interrogations.
A bientôt. -
Salut BadGuitarist,
C'est super génial ce que t'envoie !!! mille merci ;-)
Avec ton cours et mes ' tites ' recherches sur net .... j'ai fini par avancer un peu !!
mise à part le temps fou que j'ai perdu à cause de pb de syntax machin ou @ du fichier .ctl que je ne marquais pas complète le reste ça va.
... quand on est débutant le chemin est long ! mais on y arrive ;-)
Pour nos moutons : impossible de faire marcher avecINFILE donnees.dat
j'ai fini par mettre mes données dans .ctl et j'ai gardé une seuleFIELDS TERMINATED BY ','
pour toutes les colonnes ça donne :
LOAD DATA INFILE * INTO TABLE maTable FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' (prenom,ville,num) BEGINDATA Jean,"Lyon",253 Marie,"Bordeaux",145 Yves,"Lille",102
et figure toi que ça marche !!!
Par contre si les données vont dans .bad comment tu les corriges et les récupères ?
et pour PL/SQL
Normalement je dois lire le chapitre ... j'espère m'y mettre bientôt...
Merci encore et à bientôt ;-) -
Quand tu charges des données, en général, on cherche aussi à faire des traitements.
Conseil 1 :
Tu peux faire des contrôles directement avec SQLLOADER en les précisant dans le fichier de contrôle (le fichier .ctl). Mais c'est compliqué car cela oblige à mieux connaître ce puissant outil.
Ce que je fais, pour profiter de mes acquis, c'est que je charge les données dans une table intermédiaire (une table de travail en quelque sorte) sur laquelle je pose un trigger sur insertion (de type BEFORE INSERT EACH ROW).
C'est par le biais de ce trigger, écris en PL/SQL, que je fais tous les contrôles et que je dispatche les informations dans les différentes tables de ma base de données.
Conseil 2 (et Qui va dans le sens du conseil 1) :
je limite le type des données à charger au type CHAR : cela évite les erreurs de typage.
Si j'ai des montants, ils sont alors exprimés sans virgule (par exemple: ils sont multipliés par 100 dans le fichier de données) et c'est dans mon trigger que je fais les conversions qui s'imposent.
A présent, c'est à toi de jouer ;-)
J'attends avec impatience le compte rendu de tes découvertes Oracle.
@+ -
... suite ... description du fichier de contrôle :
Le fichier de contrôle décrit la table d'accueil des enregistrements contenus dans le fichier de données.
Le contenu du fichier de contrôle appelé précédemment load_annuaire_SAP.ctl ressemblera à ceci :
LOAD DATA REPLACE INTO TABLE annuaire_SAP_V2 TRAILING NULLCOLS ( IDT_ASAP CHAR TERMINATED BY ";", NOM_ASAP CHAR TERMINATED BY ";", PRE_NOM_ASAP CHAR TERMINATED BY WHITESPACE )
où
REPLACE : pour indiquer que les données déjà présentes dans la table d'accueil seront écrasées
INTO TABLE : nom d la table dans laquelle tu va insérer le contenu de ton fichier de données (DATA)
IDT_ASAP : 1ière colonne de la table annuaire_SAP_V2
NOM_ASAP : 2ième colonne de la table annuaire_SAP_V2
PRE_NOM_ASAP : 3ième colonne de la table annuaire_SAP_V2
CHAR : le type de données "SQLLOADER" correspondant au type VARCHAR2 des colonnes de tables
TERMINATED BY : le séparateur de champ
remarque : sur le dernier champ, il n'ya pas le séparateur habituel d'où le mot clé WHITESPACE
... suite (conseil(s)) au prochain post ... -
... suite (description du fichier à charger) de la procédure SQLLoader ...
Le contenu du fichier de données (simple fichier texte) pointé par le paramètre DATA ressemble donc à cela :
00017478;RODRIGUEZ;MICHEL 00000042;LASAYGUES;BERNARD 00021769;CAM;TIENGKHAM
etc ...
Tu remarqueras que le séparateur de champ que j'ai choisi est le point-virgule. Tu pouvais très bien choisir le | ou la tabulation ... le principal étant de le mentionner dans le fichier de contrôle (CONTROL).
... la suite (le fichier de contrôle) au prochain post ... -
Bonjour CodeForEver,
Désolé pour la promesse de Normand. J'ai eu exceptionnellement du travail hier ;-)
La commande de lancement de SqlLoader sera du style (sur une même ligne DOS) :
C:\ORANTV9\bin\SQLLdr USERID=tonLogin/tonMotDePasse@tonSIDBD CONTROL=load_annuaire_SAP.ctl LOG=load_annuaire_SAP.log BAD=load_annuaire_SAP.bad DATA=Z_telecom.txt ERRORS=9999 ROWS=1000
oùUSERID : ta connexion BD CONTROL : description de ton chargement (je te donnerai après un exemple) LOG : fichier de traces BAD : fichier des lignes rejetées (le fichier a la même structure que le fichier de données) DATA : ton fichier de données ERRORS : nombre d'erreurs maxi. que tu acceptes de rencontrer; au delà, arrêt du chargement imposé ROWS : un COMMIT (validation) est fait toutes les n lignes chargées dans la base
... la suite au prochain post ... -
salut BadGuitarist,
j'avais envoyé le message no 9 mais entre temps j'ai avancé un peu ;-)
ton explication m'a donné l'idée de voir plus sur le sujet
sur :
https://jaouad.developpez.com/sqlldr/#LIII-A
j'ai trouvé la syntaxe pour accéder au sqlldr mais il y a encore du boulot pour que ça marche :-) -
J'aimerais bien voir ton fichier de données
-
Bonsoir CodeForEver,
Si je comprends bien, la solution sqlLoader t'intéresserait ... je te guiderai au cours de ma journée de travail (disons à partir de 10h00).
Le but du jeu est le suivant : tu as un fichier texte qui contient les enregistrements que tu veux insérer dans une table. Voici à quoi peut ressembler ton fichier de données :
valeur1Col1;valeur1Col2;valeur1Col3
valeur2Col1;valeur2Col2;valeur2Col3
valeur3Col1;valeur3Col2;valeur3Col3
...
valeurNCol1;valeurNCol2;valeurNCol3
A sqlLoader, tu donneras en paramètre de ta ligne de commande un fichier de contrôle qui indiquera dans quelle table (nom et structure) tu veux insérer ces données.
Ce qui est pas mal dans cette méthode, c'est que :
- l'outil produit un fichier de traces qui t'indiquera pourquoi telle ligne a été rejetée
- les lignes rejetées sont insérées dans un fichier BAD qui a la même structure que ton fichier de données.
Une fois l'erreur corrigée, tu peux alors relancée la commande sqlLoader en donnant en fichier de données
le fichier BAD et du coup, les données auparavant rejetées sont remises dans le circuit ;-)
@ tout'à l'heure pour le tutorial parce que là, je m'emballe ! -
Bonsoir BadGuitarist,
Merci bcp de tes réponses.
C'est super gentil ta proposition de m'aider pour la solution de sqlldr.
à savoir que je suis débutante et n'y connais pas de grand'chose si ça ne te fait pas perdre bcp de temps...
merci et à + -
Petit complément à ton prolème d'insertions multiples sous Oracle,
si tu ne te limite pas au langage SQL alors tu peux utiliser l'outil sqlloader (%ORACLE_HOME%\BIN\sqlldr.exe) qui te permettra de charger dans ta base le contenu d'un fichier texte structuré.
Si cela t'intéresse, je peux t'aider à mettre en place une telle solution. -
Bonsoir CodeForEver,
Ton 2ième tutorial respecte bien une écriture SQL standard de requête d'"insertions multiples" : cela correspond à la méthode (1) de ma réponse précédante.
- 1
- 2