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

Oracle Discussion :

update d'une table avec données d'une autre table :jointure


Sujet :

Oracle

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 19
    Points : 17
    Points
    17
    Par défaut update d'une table avec données d'une autre table :jointure
    Bonjour
    J'ai 2 tables ORACLE tb1 et tb2 identiques au niveau des colonnes soit :
    cle char(06)
    Cpteur1 number (2)
    Cpteur2 number (2)
    Cpteur3 number (2)
    Je souhaite intialiser les compteurs de la table tb1 avec ceux de la table tb2 : sachant que ts les éléments déjà pour chaque clé dans la table tb1
    j'écris donc
    update tb1
    set tb1.Cpteur1 = tb2.Cpteur1,
    tb1.Cpteur2 = tb2.Cpteur2,
    tb1.Cpteur3 = tb2.Cpteur3
    from tb2
    where tb1.cle = tb2.cle
    Et bien ça ne fonctionne pas sous ORACLE, j'ai essayé avec diverses syntaxes et toujours pareil
    Dois absolument passer par un curseur?
    Merci d'avance

  2. #2
    Membre habitué
    Inscrit en
    Août 2006
    Messages
    181
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 181
    Points : 166
    Points
    166
    Par défaut
    tu utilise la syntaxe sybase là !
    il faut faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    update tb1
    set tb1.Cpteur1 = (select tb2.Cpteur1 from tb2 where where tb1.cle = tb2.cle),
    tb1.Cpteur2 = (select tb2.Cpteur2 from tb2 where where tb1.cle = tb2.cle),
    tb1.Cpteur3 = (select tb2.Cpteur3 from tb2 where where tb1.cle = tb2.cle)
    tu pourras faire un test à la fin en plus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    update tb1
    set tb1.Cpteur1 = (select tb2.Cpteur1 from tb2 where where tb1.cle = tb2.cle),
    tb1.Cpteur2 = (select tb2.Cpteur2 from tb2 where where tb1.cle = tb2.cle),
    tb1.Cpteur3 = (select tb2.Cpteur3 from tb2 where where tb1.cle = tb2.cle)
    where exists(select 1 from tb2 where where tb1.cle = tb2.cle)

  3. #3
    Membre habitué
    Inscrit en
    Septembre 2006
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 142
    Points : 170
    Points
    170
    Par défaut
    Sinon tu peux utiliser la commande merge

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    MERGE INTO tb1 A
       USING (SELECT cpteur1, cpteur2, cpteur3 FROM tb2) B
       ON (A.cle = B.cle)
       WHEN MATCHED THEN UPDATE SET A.cpteur1 = B.cpteur1, A.cpteur2 = B.cpteur2, A.cpteur3 = B.cpteur3 
       WHEN NOT MATCHED THEN INSERT (A.cle, A.cpteur1, A.cpteur2, A.cpteur3) VALUES (B.cle, B.cpteur1, B.cpteur2, B.cpteur3);

    Attention cette commande n'est valable qu'à partir de la 9i.
    Si l'indentifiant cle n'existe pas dans tb1 alors il y a ajout d'une ligne et pas seulement update.

    En 10 g il est possible de ne faire seulement que l'update.

  4. #4
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 120
    Points : 88
    Points
    88
    Par défaut
    Citation Envoyé par Oraman
    tu utilise la syntaxe sybase là !
    Je n'ai d'ailleurs jamais compris pourquoi cette syntaxe Sybase ne fonctionnait pas sous Oracle, alors que je suis persuadé qu'elle est extrêmement plus rapide...

  5. #5
    Membre habitué
    Inscrit en
    Août 2006
    Messages
    181
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 181
    Points : 166
    Points
    166
    Par défaut
    parce qu'on est pas dans un monde parfait

  6. #6
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 120
    Points : 88
    Points
    88
    Par défaut
    Citation Envoyé par Oraman
    parce qu'on est pas dans un monde parfait
    Certes, mais en-dehors de ça, ne penses-tu pas que du coup les perfs d'un UPDATE massif de ce genre sont bien plus rapides sous Sybase ? De même pour le DELETE d'ailleurs, puisqu'on peut très bien faire sous Sybase :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    DELETE table1
    FROM table2
    WHERE table1.id = table2.id

  7. #7
    Membre habitué
    Inscrit en
    Août 2006
    Messages
    181
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 181
    Points : 166
    Points
    166
    Par défaut
    je suis tout a fait d'accord avec toi sur ce point , sutout sur des volumes importants de données ce type de requête sont plus performants sur sybase que sur oracle mais chaque SGBD a ces spécificité

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 19
    Points : 17
    Points
    17
    Par défaut
    Bonjour à tous
    J'ai essayé comme tu m'as dit ORAMAN ; le pb est que j'ai en réalité 8 compteurs à mettre à jour. Et ça rame si bien que j'ai tout stoppé pour utiliser un curseur.
    C'est vrai qu'avec SYBASE c'est bien plus évident!

  9. #9
    Membre habitué
    Inscrit en
    Août 2006
    Messages
    181
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 181
    Points : 166
    Points
    166
    Par défaut
    oui côté perf j'imagine c'est pas terrible
    est ce tu as un index sur la colonne clé dans les différentes tables et est ce que tes stat sur ces tables sont à jour ? ça pourra amiliorer les perf

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 19
    Points : 17
    Points
    17
    Par défaut
    J'ai juste un index sur une colonne clé de la table 1. En fait la table 2 c'est une table similaire que j'ai créé et maj avec des compteurs divers et variés que j'ai recalculés afin de mettre à jour la vraie table après.

    Je suis passée par cette table 2 (simili temporaire) pour faire des analyses à propos des écarts et puis pour tester mon code. Mais quand la table 1 sera OK, je la supprimerais

  11. #11
    Membre habitué
    Inscrit en
    Août 2006
    Messages
    181
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 181
    Points : 166
    Points
    166
    Par défaut
    ça aurai été mieux d'indexer le champ clé de la table 2 même si aprés tu vas tout supprimer

  12. #12
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par Oraman
    je suis tout a fait d'accord avec toi sur ce point , sutout sur des volumes importants de données ce type de requête sont plus performants sur sybase que sur oracle mais chaque SGBD a ces spécificité
    Oulala, je ne balancerai pas ce genre d'affirmation sans preuves...

    Citation Envoyé par Nico57
    Certes, mais en-dehors de ça, ne penses-tu pas que du coup les perfs d'un UPDATE massif de ce genre sont bien plus rapides sous Sybase ? De même pour le DELETE d'ailleurs, puisqu'on peut très bien faire sous Sybase :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    DELETE table1
    FROM table2
    WHERE table1.id = table2.id
    Eh bien moi, je n'en suis pas sûr... Tout dépend de comment le moteur oracle et celui de sybase traitent la requête. Il faudrait faire des tests sur des volumes très importants pour pouvoir affirmer ce genre de chose. Il ne faut tout même pas oublier qu'oracle est réputé et habitué à gérer de très gros volumes

    Par ailleurs, la manière dont tu écris tes requêtes est également important. Par exemple pour la requête de solange44, plutôt que la solution proposée par oraman, je préfère la requête suivante qui va améliorer considérablement les temps de réponse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    update tb1
    set (tb1.Cpteur1, tb1.Cpteur2, tb1.Cpteur3) = 
        (select tb2.Cpteur1, tb2.Cpteur2, tb2.Cpteur3 
        from tb2 
        where tb1.cle = tb2.cle),
    where exists(select 1 from tb2 where where tb1.cle = tb2.cle);
    Et là peu importe le nombre de compteur que tu as. Ensuite ne reste plus qu'à créer les indexes adaptés (si nécessaires) et je suis persuadé que tu auras des temps de réponse (au moins) aussi bons que ceux obtenus avec sybase.

  13. #13
    Membre habitué
    Inscrit en
    Août 2006
    Messages
    181
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 181
    Points : 166
    Points
    166
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    update tb1
    set (tb1.Cpteur1, tb1.Cpteur2, tb1.Cpteur3) = 
        (select tb2.Cpteur1, tb2.Cpteur2, tb2.Cpteur3 
        from tb2 
        where tb1.cle = tb2.cle),
    where exists(select 1 from tb2 where tb1.cle = tb2.cle);
    oups ! ça à l'aire bcp mieux
    solange tu pourras nous dire qu'est ce ça a donné chez toi cette requête

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 19
    Points : 17
    Points
    17
    Par défaut
    ca marche : environ 6mn pour 14500 lignes MAJ
    Par contre le where exists en plus n'est pas utile.
    Ceci dit, comme c'est pour un traitement batch, j'ai utilisé un curseur et je fais mes update ligne par ligne. Ca semble être rapide , le plus long a été d'écrire le curseur et la procédure après le fetch ; mais maintenant que c'est fait et que ça fonctionne tout va bien !

  15. #15
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par solange44
    ca marche : environ 6mn pour 14500 lignes MAJ
    Cela me paraît bien long !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SQL> create table tab1 as select owner, table_name, column_name from all_tab_columns;
    Table created.
     
    SQL> create table tab2 as select owner, table_name, column_name from all_tab_columns;
    Table created.
     
    SQL> select count(*) from tab1;
     COUNT(*)
    ---------
        43317
    Mise à jour sans index :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SQL> set timing on
    SQL> update tab1 set (table_name, column_name) = (select table_name || '_1', column_name || '_1' from tab2
      2  where tab2.owner = tab1.owner and tab2.table_name = tab1.table_name and tab2.column_name = tab1.column_name);
    43317 rows updated.
     real: 754241
    Soit environ 12 minutes.

    Mise à jour avec index :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SQL> create unique index i_tab2 on tab2(owner, table_name, column_name);
    Index created.
     real: 6703
    SQL> update tab1 set (table_name, column_name) = (select table_name || '_1', column_name || '_1' from tab2
      2  where tab2.owner = tab1.owner and tab2.table_name = tab1.table_name and tab2.column_name = tab1.column_name);
    43317 rows updated.
     real: 5249
    5s... Le résultat est flagrant.

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

Discussions similaires

  1. [XL-2010] sélection des données depuis une base de données depuis une autre feuille
    Par Learning everyday dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 05/11/2014, 10h14
  2. Réponses: 14
    Dernier message: 23/04/2012, 22h32
  3. inserer les données d'une base de données dans une autres?
    Par enstein8 dans le forum MS SQL Server
    Réponses: 8
    Dernier message: 14/10/2011, 13h33
  4. Réponses: 8
    Dernier message: 08/01/2010, 13h53

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