Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1510 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  UPDATE avec jointure

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

UPDATE avec jointure

n°1953712
Tibar
Posté le 29-12-2009 à 16:55:45  profilanswer
 

Bonjour tout le monde,
 
Je suis sous Oracle 10g et j'ai besoin de faire une requête qui me paraît toute simple :  
 
UPDATE TABLE1 T1
SET T1.Champ1 =  
SELECT T2.Champ1
FROM TABLE2 T2
INNER JOIN TABLE1 T1 ON T1.Champ2 = T2.Champ2
 
J'ai beau tourner dans tous les sens, ça me sort toujours des erreurs, pourtant je suis presque sur d'avoir déjà utilisé cette syntaxe, peut-être sur un autre SGBD...
 
Si quelqu'un a une idée...
 
Merci,

mood
Publicité
Posté le 29-12-2009 à 16:55:45  profilanswer
 

n°1953722
fred777888​999
Posté le 29-12-2009 à 17:08:52  profilanswer
 

Essaye plutot :

Code :
  1. UPDATE TABLE1 T1
  2. SET T1.Champ1 =  (
  3. SELECT T2.Champ1
  4. FROM TABLE2 T2
  5. WHERE T1.Champ2 = T2.Champ2 )

n°1953723
Tibar
Posté le 29-12-2009 à 17:13:20  profilanswer
 

Yop, j'y ai cru (ça a tourné quelques secondes...) et puis la fameuse erreur 1427 : "single-row subquery returns more than one row"...
 
Je comprends bien ce que ça veut dire, mais ça m'arrangerait de pouvoir mettre à jour toute ma table à partir des champs d'une autre table sur une jointure entre les deux...

n°1953725
Tibar
Posté le 29-12-2009 à 17:16:22  profilanswer
 

Bon ben je suis tombé la dessus :  
http://forum.hardware.fr/hfr/Progr [...] 5595_1.htm
(ça date de 2002, mon seul espoir est que ça ait été implémenté depuis, mais je n'y crois pas trop)...

n°1953726
fred777888​999
Posté le 29-12-2009 à 17:18:37  profilanswer
 

lol, ben ca veux dire que ton sous select renvoie pls lignes, comment veux-tu que oracle s'y retrouve.
Ta jointure doit se faire sur des clefs sinon c'est mort, c'est comme si tu lui demande de mettre a jour les prenoms de tous les gars dont le nom est martin juste avec leur nom.
Si toutes les valeurs sont les memes, essaye :

Code :
  1. UPDATE TABLE1 T1
  2. SET T1.Champ1 =  (
  3. SELECT MAX(T2.Champ1)
  4. FROM TABLE2 T2
  5. WHERE T1.Champ2 = T2.Champ2 )


mais a prendre avec des pincettes, tu va fusiller ta base si les valeurs sont differentes et qu'elles doivent le rester.
mais ce que tu veux probablement ecrire est

Code :
  1. UPDATE TABLE1 T1
  2. SET T1.Champ1 =  (
  3. SELECT T2.Champ1
  4. FROM TABLE2 T2
  5. WHERE T1.clef = T2.clef )

n°1953729
Tibar
Posté le 29-12-2009 à 17:26:52  profilanswer
 

Non, ce que je veux ecrire est exactement ce qui se "comprend" dans ma requête initiale, à savoir que je veux mettre à jour un champ de la table 1 à partir d'une valeur de la table 2, en ayant une clé commune entre les deux tables...
 
Par exemple, j'ai un référentiel de pays avec leur code ISO, et une table adresse avec uniquement le code ISO, et je souhaite mettre à jour le champ "libelle_pays" à partir de ma table de référence :  
 
UPDATE ADRESSE AD
SET AD.Libelle_pays =  
(SELECT REF.Libelle_pays
FROM REFERENTIEL_PAYS REF
INNER JOIN ADRESSE AD ON AD.Code_Pays = REF.Code_Pays)
 
Mon SELECT renvoie bien plusieurs lignes (autant qu'il y en a dans ma table ADRESSE), mais l'UPDATE se fait bien sur une seule ligne à la fois, même si il en fait plusieurs dans le même ensemble...
 
J'ai trouvé ça :  
 
http://geekswithblogs.net/WillSmit [...] again.aspx  
apparemment ça passe bien sous MS-SQL, et quand j'adapte avec la solution proposée, je me retrouve avec une "insuficient privilege", je continue de creuser...


Message édité par Tibar le 29-12-2009 à 17:27:34
n°1953734
Tibar
Posté le 29-12-2009 à 18:23:14  profilanswer
 

Bon alors apparemment, il existerait une syntaxe :  
 
MERGE INTO ADRESSE AD
USING (
      SELECT AD.Code_Pays cp_ad, RE.Libelle_Pays lp_re, RE.Code_Pays cp_re
      FROM ADRESSE AD, REFERENTIEL_PAYS RE
      WHERE AD.Code_Pays = RE.Code_Pays
      )  
      DRV
ON (AD.Code_Pays = DRV.cp_re)
WHEN MATCHED THEN UPDATE SET AD.Libelle_Pays = DRV.lp_re
 
mais quand j'essaie sur ma table (qui ne concerne pas des pays ni des libellés de pays), j'obtiens une erreur 30926 "unable to get a stable set of rows in the source table"...
 
La suite au prochain épisode, je pars sur un CREATE AS SELECT, au moins je sais faire une jointure, on verra pour rapatrier les données...

n°1953799
Tibar
Posté le 29-12-2009 à 23:23:03  profilanswer
 

fred777888999 a écrit :

lol, ben ca veux dire que ton sous select renvoie pls lignes, comment veux-tu que oracle s'y retrouve.
Ta jointure doit se faire sur des clefs sinon c'est mort, c'est comme si tu lui demande de mettre a jour les prenoms de tous les gars dont le nom est martin juste avec leur nom.
Si toutes les valeurs sont les memes, essaye :

Code :
  1. UPDATE TABLE1 T1
  2. SET T1.Champ1 =  (
  3. SELECT MAX(T2.Champ1)
  4. FROM TABLE2 T2
  5. WHERE T1.Champ2 = T2.Champ2 )


mais a prendre avec des pincettes, tu va fusiller ta base si les valeurs sont differentes et qu'elles doivent le rester.
mais ce que tu veux probablement ecrire est

Code :
  1. UPDATE TABLE1 T1
  2. SET T1.Champ1 =  (
  3. SELECT T2.Champ1
  4. FROM TABLE2 T2
  5. WHERE T1.clef = T2.clef )



 
En fait, je ne comprends pas pourquoi il faudrait absolument que les données de jointure dans T1 et T2 soient des clés. Apparemment Oracle estime que les données ne peuvent pas être "fiables" si la jointure ne se fait pas sur une clé... Dommage pour moi...

n°1953844
casimimir
Posté le 30-12-2009 à 09:03:57  profilanswer
 

le merge ne t'aidera pas.
 
ta requete doit avoir la gueule:

Code :
  1. UPDATE ADRESSE AD
  2. SET AD.Libelle_pays =  
  3. (SELECT REF.Libelle_pays
  4. FROM REFERENTIEL_PAYS REF
  5. WHERE AD.Code_Pays = REF.Code_Pays)


 
et si tu as 1427 : "single-row subquery returns more than one row", c'est que tu as plusieurs lignes pour un même Code_Pays dans ta table REFERENTIEL_PAYS, et donc a moins de mettre un distinct devant REF.Libelle_pays tu vas devoir établir une règle pour lui dire quelle ligne prendre
 

n°1953847
MagicBuzz
Posté le 30-12-2009 à 09:19:42  profilanswer
 

fred777888999 a écrit :

lol, ben ca veux dire que ton sous select renvoie pls lignes, comment veux-tu que oracle s'y retrouve.
Ta jointure doit se faire sur des clefs sinon c'est mort, c'est comme si tu lui demande de mettre a jour les prenoms de tous les gars dont le nom est martin juste avec leur nom.
Si toutes les valeurs sont les memes, essaye :

Code :
  1. UPDATE TABLE1 T1
  2. SET T1.Champ1 =  (
  3. SELECT MAX(T2.Champ1)
  4. FROM TABLE2 T2
  5. WHERE T1.Champ2 = T2.Champ2 )


mais a prendre avec des pincettes, tu va fusiller ta base si les valeurs sont differentes et qu'elles doivent le rester.
mais ce que tu veux probablement ecrire est

Code :
  1. UPDATE TABLE1 T1
  2. SET T1.Champ1 =  (
  3. SELECT T2.Champ1
  4. FROM TABLE2 T2
  5. WHERE T1.clef = T2.clef )



 
 
Plutôt que MAX, j'utiliserais "DISTINCT", histoire d'être sûr de planter quand même s'il y a des lignes différentes :)

mood
Publicité
Posté le 30-12-2009 à 09:19:42  profilanswer
 

n°1953855
fred777888​999
Posté le 30-12-2009 à 09:54:58  profilanswer
 

De toutes facons, tu peux mettre ce que tu veux, le probleme est celui que casimir a exprime mieux que moi. Si tu as plusieurs pays avec le meme code, comment veux-tu qu'oracle sache quel libelle mettre ?
Ca peut s'identifier avec

Code :
  1. SELECT COUNT(*), REF.Code_Pays , MAX(REF.Libelle_pays)
  2. FROM REFERENTIEL_PAYS REF
  3. GROUP BY REF.Code_Pays
  4. ORDER BY 1 DESC


et une fois ta table corrigée tu peux utiliser merge ou update c'est sans importance.

n°1953871
Tibar
Posté le 30-12-2009 à 10:16:43  profilanswer
 

Salut tout le monde,
 
En effet c'était bien un problème de doublons dans la table référentiel (cas évidemment impossible d'après les règles de gestion)... Ça m'apprendra à faire confiance à des documents plutôt que de contrôler...
 
Fred, dans ta requête pour détecter les doublons, le MAX(REF.Libelle_Pays) est juste là à titre indicatif ?
 
Enfin, 1j pour faire un update alors que la réponse était dans la question, belle performance de ma part...
 
Merci à tous,

n°1953892
fred777888​999
Posté le 30-12-2009 à 10:50:30  profilanswer
 

Oui, c'est juste pour avoir un des libelles au hasard, mais c'est normalement sur le code que tu dois travailler.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  UPDATE avec jointure

 

Sujets relatifs
[resolut]est ton obligé de renomé les produit d'une jointure?[ADO] Executer requête Update sous VB
Problème Jointure SQLProblème avec le commande update de svn sous netBeans
Requête sql avec jointure?Jointure entre 3 tables ! Help please
[Oracle] Update avec jointurefaire un update avec une jointure oracle
Requete Update avec jointure sous SQL SERVEUR[MySQL] jointure dans syntaxe update
Plus de sujets relatifs à : UPDATE avec jointure


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR