Précédent   Forum des professionnels en informatique > Bases de données > Oracle > Débuter
Débuter Forum d'entraide pour débuter avec Oracle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 07/10/2011, 14h25   #1
Membre Expert
 
Avatar de sat83
 
Homme
Développeur informatique
Inscription : mars 2004
Messages : 978
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mars 2004
Messages : 978
Points : 1 177
Points : 1 177
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...
sat83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/10/2011, 14h33   #2
Membre du Club
 
Homme Arnaud
Inscription : octobre 2002
Messages : 56
Détails du profil
Informations personnelles :
Nom : Homme Arnaud
Âge : 32
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2002
Messages : 56
Points : 66
Points : 66
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 :
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.
Dajon est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 07/10/2011, 15h08   #3
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 686
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 686
Points : 10 431
Points : 10 431
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Attention à ne pas oublier les nulls (ce n'est pas précisé, donc c'est peut-être inutile) :
Code :
1
2
3
4
5
UPDATE matable
   SET champ = nouvelle_valeur
 WHERE id = id_a_updater
   AND (champ <> nouvelle_valeur 
    OR  champ IS NULL);
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/10/2011, 15h31   #4
Membre Expert
 
Avatar de sat83
 
Homme
Développeur informatique
Inscription : mars 2004
Messages : 978
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mars 2004
Messages : 978
Points : 1 177
Points : 1 177
Merci, je vais voir pour adapter mon code en ce sens...
__________________
Ce que l'on apprend par l'effort reste toujours ancré plus longtemps...
sat83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/10/2011, 15h43   #5
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
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:

http://www.amazon.fr/Troubleshooting-Oracle-Performance-Christian-Antognini/dp/1590599179
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 Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/10/2011, 16h06   #6
Membre du Club
 
Homme Arnaud
Inscription : octobre 2002
Messages : 56
Détails du profil
Informations personnelles :
Nom : Homme Arnaud
Âge : 32
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2002
Messages : 56
Points : 66
Points : 66
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.
Dajon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/10/2011, 16h45   #7
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
[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 Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/10/2011, 16h50   #8
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 311
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 311
Points : 5 813
Points : 5 813
Citation:
Envoyé par sat83 Voir le message
...
Quelle solution vous semble la plus judicieuse? ...
Merge
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/10/2011, 17h00   #9
Membre du Club
 
Homme Arnaud
Inscription : octobre 2002
Messages : 56
Détails du profil
Informations personnelles :
Nom : Homme Arnaud
Âge : 32
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2002
Messages : 56
Points : 66
Points : 66
@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.
Dajon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/10/2011, 10h03   #10
Membre Expert
 
Avatar de sat83
 
Homme
Développeur informatique
Inscription : mars 2004
Messages : 978
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mars 2004
Messages : 978
Points : 1 177
Points : 1 177
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...
sat83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/10/2011, 10h37   #11
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 686
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 686
Points : 10 431
Points : 10 431
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
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.
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/10/2011, 11h22   #12
Membre Expert
 
Avatar de sat83
 
Homme
Développeur informatique
Inscription : mars 2004
Messages : 978
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mars 2004
Messages : 978
Points : 1 177
Points : 1 177
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 :
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...
sat83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/10/2011, 11h32   #13
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
Quelle version d'oracle ?
merge enhancements in 10g
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 10/10/2011, 11h35   #14
Membre Expert
 
Avatar de sat83
 
Homme
Développeur informatique
Inscription : mars 2004
Messages : 978
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mars 2004
Messages : 978
Points : 1 177
Points : 1 177
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...
sat83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/10/2011, 11h48   #15
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 311
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 311
Points : 5 813
Points : 5 813
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.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/10/2011, 11h51   #16
Membre Expert
 
Avatar de sat83
 
Homme
Développeur informatique
Inscription : mars 2004
Messages : 978
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mars 2004
Messages : 978
Points : 1 177
Points : 1 177
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...
sat83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/10/2011, 13h54   #17
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 311
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 311
Points : 5 813
Points : 5 813
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.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/10/2011, 10h03   #18
Membre Expert
 
Avatar de sat83
 
Homme
Développeur informatique
Inscription : mars 2004
Messages : 978
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mars 2004
Messages : 978
Points : 1 177
Points : 1 177
Voici une version simplifiée de ma requête MERGE:
Code :
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...
sat83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/10/2011, 10h41   #19
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
Vous pouvez ajouter une clause where à votre update comme dans l'exemple ci-dessous

Code :
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 Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/10/2011, 10h48   #20
Membre Expert
 
Avatar de sat83
 
Homme
Développeur informatique
Inscription : mars 2004
Messages : 978
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : mars 2004
Messages : 978
Points : 1 177
Points : 1 177
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...
sat83 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 01h17.


 
 
 
 
Partenaires

Hébergement Web