IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Un update particulier


Sujet :

Langage SQL

  1. #1
    Membre du Club
    Profil pro
    None
    Inscrit en
    Avril 2012
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : None

    Informations forums :
    Inscription : Avril 2012
    Messages : 53
    Points : 59
    Points
    59
    Par défaut Un update particulier
    Bonjour,

    J'ai besoin d'aide pour corriger une requête qui ne marche pas SVP

    Je vous explique ma situation :
    J'ai deux tables, la première t1 avec les champs : Nom, Prenom, Date et Blog (c'est le champ que je dois mettre à jour)
    et la deuxième t2 avec : Nom, Prenom, Date, Numero et Blog

    Ma requête doit vérifier une jointure, si Nom, Prenom et Date de t1 = Nom, Prenom et Date de t2 alors on met à jour t1.Blog par t2.Blog
    Et si il y a des doubles dans les lignes répondant à la jointure, alors prendre la ligne qui a le Numero le plus grand.

    J'ai essayé cette requête, mais elle me renvoie une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    update table1 t1 set t1.Blog = 
    select t2.Blog from table2 t2
    where  t1.Nom = t2.Nom
    and    t1.Prenom  = t2.Prenom
    and    t1.Date   = t2.Date
    and    t2.Numero = (select t2.Numero from table2 t2
                         inner join (select max(t2.Numero) as maximum,
                                                 Nom,Prenom,Date 
                                     from table2 t2
                                     group by Nom,Prenom,Date
                                     ) src
                         on   src.Nom=t2.Nom
                         and src.Prenom=T2.Prenom
                         and src.Date=t2.Date
                         and src.maximum=t2.Numero)


    J'aimerai aussi que ma requête soit optimisée le plus possible vu que je vais la tester sur une grande volumétrie de données, merci d'avance

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Vous n'avez pas indiqué votre message d'erreur !

    Quel est votre SGBD ?

  3. #3
    Membre du Club
    Profil pro
    None
    Inscrit en
    Avril 2012
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : None

    Informations forums :
    Inscription : Avril 2012
    Messages : 53
    Points : 59
    Points
    59
    Par défaut
    Re, je suis sur Oracle, et le message m'indique que la sous requête renvoie plusieurs lignes, du coup l'update ne peut pas se faire :\

  4. #4
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Passez par un merge : http://docs.oracle.com/cd/B28359_01/...htm#SQLRF55042


    Une explication en francais ici : http://blog.developpez.com/transacti...avec-predicats


    Concernant le message d'erreur, celui-ci indique que votre condition de jointure entre vos deux tables renvoies plusieurs lignes.

    Du coup il ne sais pas comment réaliser l'update.

  5. #5
    Membre du Club
    Profil pro
    None
    Inscrit en
    Avril 2012
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : None

    Informations forums :
    Inscription : Avril 2012
    Messages : 53
    Points : 59
    Points
    59
    Par défaut
    J'ai du mal à le faire avec un merge, c'est la première fois que j'utilise cette instruction :\

  6. #6
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Dans la doc en francais quelle partie n'avez vous pas compris ?

    Postez vos essais

  7. #7
    Membre du Club
    Profil pro
    None
    Inscrit en
    Avril 2012
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : None

    Informations forums :
    Inscription : Avril 2012
    Messages : 53
    Points : 59
    Points
    59
    Par défaut
    Voila ce que j'ai essayé avec le merge :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    merge into table1 t1
    using (
    SELECT DISTINCT  t2.Nom, t2.Prenom, t2.Date
    FROM table2 t2
    WHERE t2.Numero = (SELECT MAX (Numero) AS le_max
                          FROM table1 t3
                        where t1.Nom=t3.Nom
                       AND t1.Prenom=t3.Prenom
                       AND t1.Date=t3.Date                                        
                      GROUP BY t3.Nom,t3.Prenom,t3.Date) src
    on (t1.Nom = src.Nom
       AND t2.Prenom= src.Prenom
       AND t3.Date=src.Date
    )
    when matched then update set t1.Blog = t2.Blog

    Lors de l’exécution, ça tourne sans s'arrêter, comme une boucle infinie !
    Est ce que je suis proche de la solution ?

  8. #8
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Il serait sans doute plus efficace de passer par une fonction fenêtrée plutôt qu'une sous requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    MERGE INTO t1
    USING (
          SELECT 
            nom
            , prenom
            , dte 
            , blog 
            , ROW_NUMBER() OVER(PARTITION BY nom, prenom, dte ORDER BY numero DESC) Rn
          FROM t2
     
      ) t2
            ON (T2.nom = t1.nom
            AND t2.prenom = t1.prenom
            AND t2.dte = t1.dte
            AND Rn = 1)
    WHEN MATCHED THEN 
      UPDATE
        SET blog = t2.blog;

  9. #9
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Ceci correspond à votre besoin ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    merge into table1 target 
    USING (
    select nom, prenom, date, blog, row_number() over(partition by nom, prenom, date order by numero desc) as rnk
    from table2) src
    on (target.nom = src.nom and target.prenom = src.prenom and target.date = src.date and src.rnk = 1)
    when matched then update 
    set target.blog = src.blog


    Pour décrypter :
    - selection des lignes de la table2, en ajoutant un tri de numéro par ensemble nom / prenom / date
    - jointure des lignes de la table1 avec la table2 sur le triplet, et en ne considérant que les lignes de la table2 ayant le numéro maximum. (faites attention à ce point là je ne sais pas si c'est ce que vous voulez réellement)


    edit: bon je ne le supprimerai pas celui là Aieeeuuuuu !

  10. #10
    Membre du Club
    Profil pro
    None
    Inscrit en
    Avril 2012
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : None

    Informations forums :
    Inscription : Avril 2012
    Messages : 53
    Points : 59
    Points
    59
    Par défaut
    Les deux requêtes renvoient la même erreur : ORA-30926: unable to get a stable set of rows in the source tables

  11. #11
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Quelle requete exactement lancez-vous ?

    L’ordonnancement des lignes via la fonction de fenêtrage devrait éviter l'erreur que vous avez.

  12. #12
    Membre du Club
    Profil pro
    None
    Inscrit en
    Avril 2012
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : None

    Informations forums :
    Inscription : Avril 2012
    Messages : 53
    Points : 59
    Points
    59
    Par défaut
    Avec le merge proposé par aieeeuuuuu et vous =)

  13. #13
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    punkoff demandait la requête exacte, telle que vous l'avez adaptée. En plus clair, copiez/collez votre requête et postez la !

    Il est probable que vous ayez omis la condition sur le ROW_NUMBER()

  14. #14
    Membre du Club
    Profil pro
    None
    Inscrit en
    Avril 2012
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : None

    Informations forums :
    Inscription : Avril 2012
    Messages : 53
    Points : 59
    Points
    59
    Par défaut
    Voila ce que j'ai fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    MERGE INTO table t1 USING (
    SELECT nom, prenom, age, blog, ROW_NUMBER() OVER(PARTITION BY nom, prenom, age, blog ORDER BY numero DESC) test
          FROM table2) t2
            ON (t2.nom = t1.nom
            AND t2.prenom = t1.prenom
            AND t2.age = t1.age
            AND t2.test = 1)
    WHEN MATCHED THEN 
      UPDATE
        SET t1.blog = t2.blog;
    Si j'ai bien compris, l'erreur ORA-30926: unable to get a stable set of rows in the source tables signifie que Oracle est confus entre plusieurs lignes extraites, est ce qu'il y a moyen de ne pas faire la mise à jour dans ce cas précis et éviter l'erreur ?? Je vous remercie les gars !!

  15. #15
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    il ne faut pas partitionner par blog, sinon, en effet, malgré le test sur le numéro de ligne, vous pouvez vous retrouver avec plusieurs lignes dans la source qui correspondent à une ligne dans la cible.

    enlevez la colonne blog dans le PARTITION BY.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Un UPDATE un peu particulier
    Par wacky dans le forum Requêtes
    Réponses: 11
    Dernier message: 15/06/2011, 01h26
  2. [MySQL] Update doublé sur un pc en particulier
    Par BertilHeyne dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 16/01/2011, 14h30
  3. Update sur un champ particulier
    Par Pfeffer dans le forum Oracle
    Réponses: 7
    Dernier message: 31/10/2006, 13h53
  4. Probleme d'update particulier
    Par jcachico dans le forum Requêtes
    Réponses: 2
    Dernier message: 07/07/2006, 11h16
  5. update et virgule
    Par Delph dans le forum Bases de données
    Réponses: 8
    Dernier message: 27/08/2002, 14h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo