Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

SQL

7 réponses
Avatar
I.G.LOG
Bonjour à tous,
Je me pose depuis toujours une question concernant le langage SQL lorsqu'on
veut modifier un enregistrement s'il existe et, dans la cas contraire, le
créer. (je travaille actuellement avec une base MySQL 4.1)
En SQL je ne connais qu'une méthode: effectuer un "select", puis tester le
résultat ; si l'enregistrement existe on lance une requete "update", dans le
cas contraire un "insert". Le problème c'est que le update doit relancer la
recherche alors qu'elle a déjà été faite avec le select !!! Ca fait beaucoup
de trafic sur le câble, alors que SQL est sensé limiter ce trafic justement.
Ce problème ne se pose pas en langage "classique" puisque la recherche se
positionne sur l'enregistrement, il suffit alors de procéder à la modif.
Il y a la fonction "replace" qui, à priori, permettait de résoudre ce
problème. Mais je l'ai complètement abandonnée pour deux raisons:
1- elle n'est pas applicable sur les tables ne comportant pas de clé
primaire
2- il faut passer tous les champs dans la requète, car en cas de modif, ceux
qui ne sont pas passés sont réinitialisés à la valeur par défaut (c'est un
problème majeur qui m'a fait abandonner cette fonction)
Connaissez vous une astuce pour optimiser ces traitements ? (les curseurs ?
peut-être, mais je ne connais pas ce principe)
Merci

7 réponses

Avatar
Firetox
Bonjour,

utiliser insert de façon particuliere :

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]

par contre si la table n'a pas de cle alors cela va etre difficile
ou alors tu peux identifier l'enregistrement meme s'il n'y a pas de cle

petite question sur ta table comment identifie tu l'enregistrement s'il n'y
a pas de cle ?
peux etre une solution avec un insert .... (select .......) qui referait
toutes la table le select se chargeant d'avoir les nouveaux et les ancien

par exemple j'avais un code qui pouvais faire ca en insert ......(select)
le select etait une union (premiere partie : tous les enreg a mettre a jour
la deuxieme partie de l'union les nouveaux qui sont donc inserer

Bon dev
@+

"I.G.LOG" a écrit dans le message de
news:4a694a6f$0$17771$
Bonjour à tous,
Je me pose depuis toujours une question concernant le langage SQL
lorsqu'on veut modifier un enregistrement s'il existe et, dans la cas
contraire, le créer. (je travaille actuellement avec une base MySQL 4.1)
En SQL je ne connais qu'une méthode: effectuer un "select", puis tester le
résultat ; si l'enregistrement existe on lance une requete "update", dans
le cas contraire un "insert". Le problème c'est que le update doit
relancer la recherche alors qu'elle a déjà été faite avec le select !!! Ca
fait beaucoup de trafic sur le câble, alors que SQL est sensé limiter ce
trafic justement. Ce problème ne se pose pas en langage "classique"
puisque la recherche se positionne sur l'enregistrement, il suffit alors
de procéder à la modif.
Il y a la fonction "replace" qui, à priori, permettait de résoudre ce
problème. Mais je l'ai complètement abandonnée pour deux raisons:
1- elle n'est pas applicable sur les tables ne comportant pas de clé
primaire
2- il faut passer tous les champs dans la requète, car en cas de modif,
ceux qui ne sont pas passés sont réinitialisés à la valeur par défaut
(c'est un problème majeur qui m'a fait abandonner cette fonction)
Connaissez vous une astuce pour optimiser ces traitements ? (les curseurs
? peut-être, mais je ne connais pas ce principe)
Merci



Avatar
I.G.LOG
Bonjour Firetox,

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]

par contre si la table n'a pas de cle alors cela va etre difficile
ou alors tu peux identifier l'enregistrement meme s'il n'y a pas de cle

petite question sur ta table comment identifie tu l'enregistrement s'il
n'y a pas de cle ?



Par exemple j'ai une table de "liens" come suit:

t_donnc.ID_LIGNE
t_donnc.ID_COL
t_donnc._VALEUR

le couple (ID_LIGNE,ID_COL) est "à priori" toujours unique; c'est pour ça
que je n'ai pas utilisé de clé primaire (d'identifiant)
Nota: je dis "à priori" car ce n'est pas toujours vrai ! cette table permet
de gérer des métadonnées, ID_COL étant un pointeur sur un nom de champ. Les
doublons peuvent exister : cas, par exemple, d'un article étant à la fois un
bateau et un avion - les hydravions !
ID_LIGNE donne l'identifiant de l'article, ID_COL celui du champ "type" et
_VALEUR est le pointeur sur la table "catégorie d'articles".
Il n'y aura jamais de doublons sur les trois champs. C'est comme ça que
j'identifie l'enregistrement, sur les trois champs grace à un
"select ... where ID_LIGNE = x and ID_COL = y and _VALEUR = z"....
et donc, comme je le disais, en cas de update je dois faire
"update t_donnc set ID_LIGNE = x1, ID_COL = y1, _VALEUR = z1 where ID_LIGNE
= x and ID_COL = y and _VALEUR = z"
Bien sûr, j'avais pensé mettre un identifiant unique, mais ca augmente
beaucoup le volume pour disposer d'une information "peu pertinente" je
trouve.
En tous cas, le INSERT ... ON DUPLICATE KEY UPDATE est inapplicable dans ce
cas


peux etre une solution avec un insert .... (select .......) qui referait
toutes la table le select se chargeant d'avoir les nouveaux et les ancien

par exemple j'avais un code qui pouvais faire ca en insert ......(select)
le select etait une union (premiere partie : tous les enreg a mettre a
jour la deuxieme partie de l'union les nouveaux qui sont donc inserer




euh... je ne comprends pas bien !

Merci
Avatar
JeAn-PhI
I.G.LOG a exposé le 24/07/2009 :
Bonjour Firetox,

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]

par contre si la table n'a pas de cle alors cela va etre difficile
ou alors tu peux identifier l'enregistrement meme s'il n'y a pas de cle

petite question sur ta table comment identifie tu l'enregistrement s'il n'y
a pas de cle ?



Par exemple j'ai une table de "liens" come suit:

t_donnc.ID_LIGNE
t_donnc.ID_COL
t_donnc._VALEUR

le couple (ID_LIGNE,ID_COL) est "à priori" toujours unique; c'est pour ça que
je n'ai pas utilisé de clé primaire (d'identifiant)
Nota: je dis "à priori" car ce n'est pas toujours vrai ! cette table permet
de gérer des métadonnées, ID_COL étant un pointeur sur un nom de champ. Les
doublons peuvent exister : cas, par exemple, d'un article étant à la fois un
bateau et un avion - les hydravions !
ID_LIGNE donne l'identifiant de l'article, ID_COL celui du champ "type" et
_VALEUR est le pointeur sur la table "catégorie d'articles".
Il n'y aura jamais de doublons sur les trois champs. C'est comme ça que
j'identifie l'enregistrement, sur les trois champs grace à un
"select ... where ID_LIGNE = x and ID_COL = y and _VALEUR = z"....
et donc, comme je le disais, en cas de update je dois faire
"update t_donnc set ID_LIGNE = x1, ID_COL = y1, _VALEUR = z1 where ID_LIGNE =
x and ID_COL = y and _VALEUR = z"
Bien sûr, j'avais pensé mettre un identifiant unique, mais ca augmente
beaucoup le volume pour disposer d'une information "peu pertinente" je
trouve.
En tous cas, le INSERT ... ON DUPLICATE KEY UPDATE est inapplicable dans ce
cas


peux etre une solution avec un insert .... (select .......) qui referait
toutes la table le select se chargeant d'avoir les nouveaux et les ancien

par exemple j'avais un code qui pouvais faire ca en insert ......(select)
le select etait une union (premiere partie : tous les enreg a mettre a jour
la deuxieme partie de l'union les nouveaux qui sont donc inserer




euh... je ne comprends pas bien !

Merci



vous pourriez mettre dans votre cas un id auto uniquement pour
identifier de façon unique l'enreg lors de la maj ?

--
Cordialement JeAn-PhI
Avatar
I.G.LOG
Bonjour,


vous pourriez mettre dans votre cas un id auto uniquement pour identifier
de façon unique l'enreg lors de la maj ?




c'est justement ce que je voulais éviter. car l'identifant dans ce cas ne
servirai qu'au "confort de programmation" lors des mises à jour. Et je
trouvais qu'alourdir la base pour ça ne représentait pas beaucoup d'interêt.
C'est pour ça que je cherche une autre solution, du type "curseur" (en
quelque sorte une astuce qui permettrait après le select d'effectuer
l'update sans clause where)
Avatar
news.online.fr
Le Fri, 24 Jul 2009 09:50:50 +0200, I.G.LOG a écrit:

Bonjour,


vous pourriez mettre dans votre cas un id auto uniquement pour
identifier
de façon unique l'enreg lors de la maj ?




c'est justement ce que je voulais éviter. car l'identifant dans ce cas ne
servirai qu'au "confort de programmation" lors des mises à jour. Et je
trouvais qu'alourdir la base pour ça ne représentait pas beaucoup
d'interêt.
C'est pour ça que je cherche une autre solution, du type "curseur" (en
quelque sorte une astuce qui permettrait après le select d'effectuer
l'update sans clause where)





Bonjour,

Il me semble....

Je ne sais pas quelle est la base distante, mais
.on peut utiliser des clés concaténées évitant d'avoir un identifiant en
plus si la clé concaténée est unique
.on peut lors du select ramener des identifiants 'internes' par exemple
les rowid avec oracle

Par ailleurs ,si il s'agit d'une vraie base:
.le update ... where est traité en totalité sur le serveur et il n'y a pas
de trafic réseau supplémentaire
.les données sont très probablement en cache mémoire de la base sur le
serveur


--
TT
Avatar
I.G.LOG
Bonjour



Je ne sais pas quelle est la base distante, mais



je travaille avec MySQL 4.1

.on peut utiliser des clés concaténées évitant d'avoir un identifiant en
plus si la clé concaténée est unique
.on peut lors du select ramener des identifiants 'internes' par exemple
les rowid avec oracle



oui, mais je ne suis pas très partisan des clés concaténées. On perd en
lisibilité en on gangne en complexité... je trouve en tous cas.
les rowid d'Oracle seraient peu-être ce que je cherche. Mais probablement
pas disponibles sur MySQL ?!


Par ailleurs ,si il s'agit d'une vraie base:
.le update ... where est traité en totalité sur le serveur et il n'y a pas
de trafic réseau supplémentaire
.les données sont très probablement en cache mémoire de la base sur le
serveur



bien sûr, mais j'aurais voulu éviter le code "update... where" qui est bien
souvent cause d'erreurs !!



--
TT


Avatar
Daniel
I.G.LOG a écrit :
Bonjour


Je ne sais pas quelle est la base distante, mais



je travaille avec MySQL 4.1

.on peut utiliser des clés concaténées évitant d'avoir un identifiant en
plus si la clé concaténée est unique
.on peut lors du select ramener des identifiants 'internes' par exemple
les rowid avec oracle



oui, mais je ne suis pas très partisan des clés concaténées. On perd en
lisibilité en on gangne en complexité... je trouve en tous cas.
les rowid d'Oracle seraient peu-être ce que je cherche. Mais probablement
pas disponibles sur MySQL ?!

Par ailleurs ,si il s'agit d'une vraie base:
.le update ... where est traité en totalité sur le serveur et il n'y a pas
de trafic réseau supplémentaire
.les données sont très probablement en cache mémoire de la base sur le
serveur



bien sûr, mais j'aurais voulu éviter le code "update... where" qui est bien
souvent cause d'erreurs !!


--
TT








ON DUPLICATE KEY fonctionne sur PK ou Index Unique.

Maintenant je présume que tu as du mettre un index unique formé par
t_donnc.ID_LIGNE, t_donnc.ID_COL , t_donnc._VALEUR. Si ce n'est pas le
cas tu devrais le faire car laisser à la couche cliente gérer l'unicité
des clés est le meilleur moyen d'avoir des données incohérentes.


--
suivre ce lien pour répondre:
http://cerbermail.com/?2KrV3YZXnn
Daniel
;-)