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 :

Contrôler UPDATE d'une table


Sujet :

Oracle

  1. #1
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut Contrôler UPDATE d'une table
    Bonjour à tous,
    J'ai un programme (C++) qui réalise des requêtes UPDATE cycliquement sur une table.

    Le problème, c'est que je ne dois pas effectuer la mise à jour de l'enregistrement si la valeur du champ NOM_DU_CHAMP est inchangée.

    Juste avant d'effectuer la requête UPDATE, j'effectue un SELECT pour récupérer l’enregistrement existant, et je n'effectue l'UPDATE uniquement si la valeur de NOM_DU_CHAMP est différente.

    Ne serait-il pas mieux d'effectuer les UPDATE dans mon programme C++ sans me poser de question, et d'ajouter un TRIGGER BEFORE UPDATE à ma table qui annulerait l'UPDATE si nécessaire.

    Quelle solution vous semble la plus judicieuse? Si c'est celle du Trigger, comment annuler l'UPDATE si l'ancienne et la nouvelle valeur du champ sont identique?

    Merci d'avance pour vos conseils.

    PS: A noter qu'il y a plus d'UPDATE annulé qu'effectué.
    Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...

  2. #2
    Membre régulier
    Homme Profil pro
    Inscrit en
    Octobre 2002
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2002
    Messages : 58
    Points : 86
    Points
    86
    Par défaut
    Bonjour,

    Pourquoi ne pas inclure le test dans ton update, cela éviterait de perdre du temps à récupérer la valeur d'abord et cela me semble plus "naturel" (enfin bon c'est personnel )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    update matable
    set champ=nouvelle_valeur
    where id = id_a_updater
    and champ != nouvelle_valeur
    Ainsi l'update n'est réalisé que si les valeurs sont différentes, pas besoin de select l'ancienne valeur, et pas de trigger.

    [Edit] Je pense que c'est plus judicieux de faire comme cela car:
    - Pas de logique superflue dans ton code
    - Pas de trigger, j'évite au maximum d'en utiliser car je trouve que leur coût en terme de maintenance est souvent élevé (tout le monde les oublie, et on perd a chaque fois du temps à chercher à droite a gauche l'origine d'un problème, avant de penser aux triggers)
    - Je pense qu'un update réalisé comme cela est globalement moins coûteux qu'un select systématique ou un trigger systématique pour vérifier les valeurs. Je n'ai pas vérifié ce point.
    Tuning and optimization are not a fix to a bad design. A good design is a fix to a bad design.

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Attention à ne pas oublier les nulls (ce n'est pas précisé, donc c'est peut-être inutile) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    UPDATE matable
       SET champ = nouvelle_valeur
     WHERE id = id_a_updater
       AND (champ <> nouvelle_valeur 
        OR  champ IS NULL);

  4. #4
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut
    Merci, je vais voir pour adapter mon code en ce sens...
    Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...

  5. #5
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Points : 1 359
    Points
    1 359
    Par défaut
    Citation Envoyé par sat83 Voir le message
    Bonjour à tous,
    J'ai un programme (C++) qui réalise des requêtes UPDATE cycliquement sur une table.
    Attention aussi aux ''bind variables''. Pensez à mettre votre update dans une procédure PL/QL stockée afin que le soucis des ''binds variables'' ne se posera pas pour vous.

    Pensez aussi à l'appel de cette procédure. Il faudrait que vous l'appelliez en utilisant des ''binds variables'' si elle contient des paramètres. Pour cela vous devez utilisez OCI interface OCIStmtPrepare2 et OCIDefineByPos. Je ne suis pas un spécialiste de ce qui précède mais vous pouvez trouvez des détails sur ceci dans le livre de Chistian Antognini:

    Troubleshooting Oracle Performance: Amazon.fr: Christian Antognini: Livres anglais et ?trangers@@AMEPARAM@@http://ecx.images-amazon.com/images/I/41gzv67MNfL.@@AMEPARAM@@41gzv67MNfL

    Si vous ne le faites pas correctement vous allez remplir la mémoire (v$sql) de vos appels à la procédure.

    http://hourim.wordpress.com/2011/06/...ing-parameter/
    Bien Respectueusement
    www.hourim.wordpress.com

    "Ce qui se conçoit bien s'énonce clairement"

  6. #6
    Membre régulier
    Homme Profil pro
    Inscrit en
    Octobre 2002
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2002
    Messages : 58
    Points : 86
    Points
    86
    Par défaut
    Utiliser des bind variable est une bonne pratique, mais ce n'est pas toujours possible (Risque de régression dans une appli existante, pas le temps, ou choix projet: "nan, on veut pas appeler de procédure et pis c'est tout").

    Dans ce cas, il y a aussi le paramètre CURSOR_SHARING, qui peut être intéressant il me semble.

    Mais s'il n'y a pas de problème de performance relatif à ces updates, je ne sais pas si sat83 à besoin de se poser ces questions
    Tuning and optimization are not a fix to a bad design. A good design is a fix to a bad design.

  7. #7
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Points : 1 359
    Points
    1 359
    Par défaut
    [QUOTE=Dans ce cas, il y a aussi le paramètre CURSOR_SHARING, qui peut être intéressant il me semble.
    QUOTE]

    Dans ce cas je pense que vous n'avez pas lu le lien que j'ai proposé.
    Bien Respectueusement
    www.hourim.wordpress.com

    "Ce qui se conçoit bien s'énonce clairement"

  8. #8
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par sat83 Voir le message
    ...
    Quelle solution vous semble la plus judicieuse? ...
    Merge

  9. #9
    Membre régulier
    Homme Profil pro
    Inscrit en
    Octobre 2002
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2002
    Messages : 58
    Points : 86
    Points
    86
    Par défaut
    @Mohamed: Oui, j’avoue, je n'ai pas pris le temps de lire votre article dans le détail mea maxima culpa. Je ne savais pas que le cursor sharing à force ne fonctionnait pas pour des appel à du PL depuis une application tierce. Merci
    Tuning and optimization are not a fix to a bad design. A good design is a fix to a bad design.

  10. #10
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut
    Citation Envoyé par mnitu Voir le message
    Merge
    En faite j'utilise effectivement un MERGE.
    Si l'enregistrement existe j'effectue un UPDATE, et si il n'existe pas encore j'effectue un INSERT.

    Maintenant je souhaiterais ajouter la nuance: si l'enregistrement existe et que 3 champs sont identiques, je ne fais rien.

    J'aurais pensé utiliser une clause WHERE dans le UPDATE du MERGE, mais apparemment ce n'est pas possible. J'avou ne pas être trop à l'aise avec le MERGE.

    Est ce que ca vous semble possible comme fonctionnement avec un MERGE de faire soit un INSERT, soit un UPDATE, soit RIEN?
    Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...

  11. #11
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par sat83 Voir le message
    J'aurais pensé utiliser une clause WHERE dans le UPDATE du MERGE, mais apparemment ce n'est pas possible. J'avoue ne pas être trop à l'aise avec le MERGE.
    Vous pouvez !
    Mettez votre clause WHERE avant la clause WHEN NOT MATCHED THEN INSERT.

  12. #12
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Mettez votre clause WHERE avant la clause WHEN NOT MATCHED THEN INSERT.
    Malheureusement ça ne fonctionne pas...
    Mon MERGE fonctionne bien, mais j'ai une erreur lorsque j'ajoute une clause WHERE dans l'UPDATE:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    [...]
    WHEN MATCHED THEN UPDATE SET
    [...]
    WHERE NOM_DU_CHAMP = '1500'  -- ça fonctionne sans cette ligne
    WHEN NOT MATCHED THEN INSERT (
    [...]
    Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...

  13. #13
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Quelle version d'oracle ?
    merge enhancements in 10g

  14. #14
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut
    ORACLE 9.i
    Je pense que ça doit venir de là... Ca ne doit fonctionner qu'avec la version 10.

    Je pense que dans mon programme C++ je vais remplacer mon MERGE par un SELECT suivi d'un INSERT, d'un UPDATE ou de RIEN selon le cas...
    Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...

  15. #15
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par sat83 Voir le message
    ...
    Maintenant je souhaiterais ajouter la nuance: si l'enregistrement existe et que 3 champs sont identiques, je ne fais rien.
    ...
    Ne sélectionnez pas ces enregistrements.

  16. #16
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut
    Je pensais que si je ne sélectionnais pas ces enregistrements, la requête MERGE effectuerait un INSERT, non?
    Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...

  17. #17
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Pour un ensemble des enregistrements sélectionnés le merge fait soit insert soit update. Si parmi ces enregistrements ne figure pas celles qui existent déjà dans la table à mettre à jour et qui respectent certaines critères alors il n’y aurait pas de problème.

  18. #18
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut
    Voici une version simplifiée de ma requête 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
    17
    18
    19
    20
    21
    22
    23
    MERGE INTO NOM_DE_LA_TABLE T1
    USING ( SELECT 
    'vvv'    NOM_CHAMP_1 ,
    'www'    NOM_CHAMP_2 , 
    'xxx'    NOM_CHAMP_3 , 
    'yyy'    NOM_CHAMP_4 , 
    'zzz'    NOM_CHAMP_5 , 
     
     FROM DUAL ) REF_FIELDS
    --CONDITIONS DE CORRESPONDANCES
    ON ( 
          T1.NOM_CHAMP_1 = REF_FIELDS.NOM_CHAMP_1  AND
          T1.NOM_CHAMP_2 = REF_FIELDS.NOM_CHAMP_2  AND 
          T1.NOM_CHAMP_3 = REF_FIELDS.NOM_CHAMP_3  AND 
          T1.NOM_CHAMP_4 = REF_FIELDS.NOM_CHAMP_4  AND 
          T1.NOM_CHAMP_5 = REF_FIELDS.NOM_CHAMP_5       )
    --SI CORRESPONDANCE => UPDATE
    WHEN MATCHED THEN UPDATE SET
    --[...] Liste des champs mis à jour
     
    --SINON => INSERT
    WHEN NOT MATCHED THEN INSERT ( /*[...] */ ) 
    VALUES ( /*[...] */ )
    A quel niveau est-ce que je dois placer le critère? (dans mon exemple, le critère porte sur 3 champs qui ne sont pas les champs 1 à 5 )...
    J'aimerais que si l'enregistrement existe ET si les 3 champs (6 à 8 par exmeple) son identiques à ceux existant ALORS je ne fais RIEN (ni INSERT ni UPDATE)
    Merci d'avance pour vos éclaircissement!
    Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...

  19. #19
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Points : 1 359
    Points
    1 359
    Par défaut
    Vous pouvez ajouter une clause where à votre update comme dans l'exemple ci-dessous

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    mhouri > drop table t_emp purge;
     
    Table dropped.
     
    mhouri > create table t_emp as select * from emp;
     
    Table created.
     
    mhouri > MERGE INTO t_emp
      2  using (select
      3           b.empno
      4          ,b.ename
      5          ,b.job
      6          ,b.mgr
      7          ,b.hiredate
      8          ,b.sal
      9          ,b.comm
     10          ,b.deptno
     11        from
     12          emp b) e
     13  ON    (e.empno = t_emp.empno)
     14  WHEN MATCHED THEN
     15       update
     16       set    t_emp.sal   =  e.sal ,
     17              t_emp.comm  =  e.comm
     18       where
     19             t_emp.deptno  != e.deptno
     20       and   t_emp.mgr      != e.mgr
     21       and   t_emp.hiredate != e.hiredate
     22  ;
     
    0 rows merged.
     
    mhouri > update t_emp
      2  set mgr = 7698
      3  , hiredate = sysdate
      4  , deptno  = 30
      5  where empno = 7369;
     
    1 row updated.
     
    mhouri > MERGE INTO t_emp
      2  using (select
      3           b.empno
      4          ,b.ename
      5          ,b.job
      6          ,b.mgr
      7          ,b.hiredate
      8          ,b.sal
      9          ,b.comm
     10          ,b.deptno
     11        from
     12          emp b) e
     13  ON    (e.empno = t_emp.empno)
     14  WHEN MATCHED THEN
     15       update
     16       set    t_emp.sal   =  e.sal ,
     17              t_emp.comm  =  e.comm
     18       where
     19             t_emp.deptno  != e.deptno
     20       and   t_emp.mgr      != e.mgr
     21       and   t_emp.hiredate != e.hiredate
     22  ;
     
    1 row merged.
    Bien Respectueusement
    www.hourim.wordpress.com

    "Ce qui se conçoit bien s'énonce clairement"

  20. #20
    Membre expérimenté
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Points : 1 307
    Points
    1 307
    Par défaut
    Malheureusement, comme expliqué plus haut, la clause WHERE ne fonctionne pas dans un MERGE sous ORACLE 9.i
    Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Update d une table avec plusieurs valeurs
    Par Nadaa dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 17/05/2006, 08h58
  2. Update d'une table à partir d'une autre
    Par nicoaix dans le forum Access
    Réponses: 5
    Dernier message: 09/03/2006, 11h36
  3. Update d'une table a partir d'une autre table
    Par Yannis06 dans le forum Oracle
    Réponses: 6
    Dernier message: 11/08/2005, 11h32
  4. Update d'une table
    Par EssaiEncore dans le forum Langage SQL
    Réponses: 2
    Dernier message: 18/02/2005, 10h00
  5. UPDATE d'une table avec test d'un champ d'une autre table
    Par delphim dans le forum Langage SQL
    Réponses: 2
    Dernier message: 03/05/2004, 12h30

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