Précédent   Forum des professionnels en informatique > Bases de données > Firebird > SQL
SQL Forum d'entraide sur le SQL pour Firebird
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 30/11/2004, 03h24   #1
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
Par défaut update et jointure

Code :
1
2
3
4
UPDATE client
SET 	a.type_client	=	b.type_client
FROM client a,vs_contrimm b
WHERE a.code_client=b.code_client
Voici un Update qui marche fort bien avec Sybase par exemple et qui sauf erreur de ma part ne sort pas des spécifications SQL standard.

Quelle est la syntaxe permettant de faire le même type d'opérations avec Interbase ?

(message d'erreur : token unknown from)

Message édité par Barbibulle : Merci d'utiliser les balises "Code" pour une meilleur lecture de vos messages.
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/11/2004, 10h02   #2
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Par défaut Re: update et jointure

Je ne sais pas si votre ordre fonctionne bien sous SyBase mais la norme SQL veut dans ce cas là qu'on utilise un sous select.
Et celà s'écrit comme ceci :
Code :
1
2
3
4
UPDATE client
  SET a.type_client = (SELECT b.type_client
                         FROM client a,vs_contrimm b
                         WHERE a.code_client=b.code_client)
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 01h42   #3
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
Par défaut update et jointure

Sur Sybase ça a bien marché pendant un an toute les nuits.

Cela dit la syntaxe proposée renvoie le message "multiple rows un singleton select" sur Interbase car dans ce cas la clause select remplace une valeur constante qui va être affectée à toutes les lignes de la table client.

Cela n'est pas ce que je souhaite. je souhaite faire une jointure qui permet de donner des valeurs différentes à chaque ligne concernée de la table client.

Il faut donc nécessairement que la table client possède une clause where dans la clause update.

Dans le sujet curseur j'explique comment j'ai résolu le problème.
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 09h48   #4
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Par défaut Re: update et jointure

Citation:
Envoyé par frantzgac
Sur Sybase ça a bien marché pendant un an toute les nuits.
Ah donc si c'est pas une erreur de frappe de votre part et que ca fonctionne sous Sybase, sachez que ce n'est pas une commande normalisé SQL (du moins pas à ma connaissance). De plus je ne comprend pas bien comment celà marche ou du moins ce que celà est censé faire.

Citation:
Envoyé par frantzgac
Cela dit la syntaxe proposée renvoie le message "multiple rows un singleton select" sur Interbase car dans ce cas la clause select remplace une valeur constante qui va être affectée à toutes les lignes de la table client.
Oui bien entendu il faut que le sous select ne renvoie qu'une seule valeur (donc en général sa clause where attaque la clé primaire)

Citation:
Envoyé par frantzgac
Cela n'est pas ce que je souhaite. je souhaite faire une jointure qui permet de donner des valeurs différentes à chaque ligne concernée de la table client.

Il faut donc nécessairement que la table client possède une clause where dans la clause update.

Dans le sujet curseur j'explique comment j'ai résolu le problème.
Je vais regarder le sujet Curseur car là j'avoue ne pas comprendre ce que vous voulez faire.
Un update de la colonne type_client de la table client mais avec plusieures valeurs ?? Bref c'est pas bien clair.
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 16h03   #5
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
c'est simple

voici la table client
code-client type client
0, null
1, null
2, C

voici la table conrimm
code-client type client
0,A
1,X
2,Z

Lorsque la requête sera executée j'aurai une table client comme cici
code-client type client
0, A
1, X
2, Z

Il s'agit d'une mise à jour avec jointure. Je ne sais toujours pas si cela peut se faire avec Interbase d'ailleurs.

Cela dit le problème est résolu avec un for select et une procédure d'usage éphemère.

ps : je ne comprends pas l'allusion à une faute de frappe.
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 16h19   #6
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Citation:
Envoyé par frantzgac
ps : je ne comprends pas l'allusion à une faute de frappe.
C'est que je pensais au départ que vous aviez fait une faute de frappe car la syntaxe que vous utiliser ne fait pas partie de la norme SQL.

Et je maintient ce que j'ai dit au départ (après relecture je m'apperçois que j'ai fait une erreur) :
Code :
1
2
3
4
UPDATE client a
  SET a.type_client = (SELECT b.type_client 
                         FROM vs_contrimm b 
                         WHERE a.code_client=b.code_client)
Celà est plus à la norme SQL.
Et donc cette update fonctionnera uniquement si le
Code :
1
2
3
SELECT b.type_client 
                         FROM vs_contrimm b 
                         WHERE a.code_client=b.code_client
ne retourne qu'une seule valeur.
Ce qui est le cas dans votre exemple.
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 16h38   #7
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
Euh non pas tout à fait, dans mon exemple on a trois mises à jour successives parce que la jointure envoie trois valeurs qui servent d'index à la mise à jour.

Quelle est à votre avis la synatxe permettant de faire cela en Interbase ?

J'a essayé ceci

update client contrimm
set client.type_client=contrimm.type_client
where client.code_client=contrimm.code_client

qui ne déclenche pas de message d'erreur mais ne fait pas non plus la mise à jour.
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 16h45   #8
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Je maintiens ce que j'ai dit l'update que je vous ai donné fonctionne parfaitement avec le jeux de données que vous avez donné.

car le sous select :
Code :
1
2
3
SELECT b.type_client 
                         FROM vs_contrimm b 
                         WHERE a.code_client=b.code_client
retrourne qu'une et une seule valeur par ligne a mettre a jour(par code_client dans votre cas).

Si l'update que je vous ai donné ne fonctionne pas et notamment donne le message d'erreur : "multiple rows un singleton select"
C'est qu'il y a des doublons (sur la colonne code_client) dans votre table vs_contrimm. Dans ce cas le SGBD ne sais pas faire et plutot que d'affecter une des valeurs possible vous indique qu'il y a un probleme.
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 16h47   #9
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
UPDATE titres
SET cumulannuel_ventes = cumulannuel_ventes qt
FROM titres, ventes
WHERE titres.id_titre = ventes.id_titre
AND ventes.date_cmd in (SELECT MAX(ventes.date_cmd) FROM ventes)

voici un exemple similaire extrait d'un cours Transac-SQL qui parait il est compatible avec Oracle et MS-SQL ce qui n'est déjà pas mal...
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 16h52   #10
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
Je vois ce que vous voulez dire concernant les doublons. Toutefois il faut bien dans la clause update (et en dehors du sous select) savoir quelle est la table correspondante au champ de contrimm servant à la mise à jour.

Par conséquent où doit être indiqué le nom de la table contrimm ?

update client contrimm ne fait pas d'erreur mais ne met pas à jour
la clause from n'existe pas dans update interbase
update client,contrimm provoque une erreur de syntaxe
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 17h35   #11
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Le probleme c'est que vous n'essayez même pas les solutions qu'on vous donnes donc à quoi ca sert de continuer ??

Je vais tout de même expliquer cet ordre SQL :

Code :
1
2
3
4
UPDATE client a 
  SET a.type_client = (SELECT b.type_client 
                         FROM vs_contrimm b 
                         WHERE a.code_client=b.code_client)
Que voulez vous mettre à jour ?
réponse : la colonne Type_client de la table client.
Ceci peut être fait comme grace à un update:
Code :
1
2
UPDATE CLIENT 
 SET TYPE_CLIENT = 'A';
Cette commande va mettre un A à tout les types_client de la table client...
Jusque là c'est simple.
Mais ce c'est pas ce que vous cherchez. Vous voulez que type_client prenne la valeur de la colonne type_client de la table vs_contrimm qui a le même code_client.

Comment rechercher la valeur type_client de la table vs_contrimm pour le client ayant le code_client=1 ?
Code :
SELECT b.type_client FROM vs_contrimm WHERE b.Code_client=1
Donc pour mettre à jour le client ayant le code 1 il faudrait faire

Code :
1
2
3
UPDATE CLIENT A
  SET TYPE_CLIENT=(SELECT b.type_client FROM vs_contrimm WHERE b.Code_client=1)
WHERE CODE_CLIENT=1
L'inconvéniant c'est qu'il faut faire autant d'update qu'il y a de client.
Heureusement dans le sous-select on peut utiliser les valeurs donnés par le UPDATE avant la mise à jour de chaque enregistrement et celà devient :

Code :
1
2
3
4
UPDATE client a 
  SET a.type_client = (SELECT b.type_client 
                         FROM vs_contrimm b 
                         WHERE a.code_client=b.code_client)
le (select b.type_client from vs_contrimm b where a.code_client=b.code_client) étant exécuté pour chaque ligne client à mettre à jour et ne doit retourner qu'une seule valeur par code_client, ce qui le cas ici.
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/12/2004, 17h39   #12
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Citation:
Envoyé par frantzgac
Code :
1
2
3
UPDATE  client contrimm
SET client.type_client=contrimm.type_client
WHERE  client.code_client=contrimm.code_client
qui ne déclenche pas de message d'erreur mais ne fait pas non plus la mise à jour.
Si il met à jour mais pas avec les valeurs que vous voulez. Votre ordre SQL est strictement equivallent à celui ci :

Code :
1
2
UPDATE  client 
SET client.type_client = client.type_client
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/12/2004, 01h17   #13
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
Par défaut Pro

Je ne vous permet pas de dire que je n'essaie pas ce qu'on me propose. C'est faux et discourtois. Vous êtes modérateur, par conséquent le moins serait que vous vous modériez vous même.

Je demande à la cantonnade s'il est possible de faire un update avec jointure sur 2 tables avec Interbase et il est possible que vous n'ayez pas la réponse, inutile de s'en prendre les uns aux autres.

Dire que ceci

update client contrimm
set client.type_client=contrimm.type_client
where client.code_client=contrimm.code_client

est équivalent à cela

update client
set client.type_client = client.type_client

me parait polémique et non technique.

Merci à vous
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/12/2004, 10h18   #14
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Par défaut Re: Pro

Citation:
Envoyé par frantzgac
Je ne vous permet pas de dire que je n'essaie pas ce qu'on me propose. C'est faux et discourtois. Vous êtes modérateur, par conséquent le moins serait que vous vous modériez vous même.
Et bien alors si vous essayez ce qu'on vous propose pourquoi ne remontez vous pas le fruit de vos essais ???? Et continuez comme si on avait rien proposé ? Si ce n'est pas de la discourtoisie, je ne m'y connais pas. Commencez donc par votre courtoisie et je m'occuperai de la mienne.

Si j'en suis arrivé à cette conclusion, c'est à cause de votre attitude, j'en suis désolé, c'est une constatation.
Relisez bien attentivement tout ce fil de conversation plutot que de prendre la mouche, vous verez que toutes les reponses s'y trouvent.

Avouez qu'il est assez ennervant pour une personne qui aide les autres que celui qui pose une question ne tienne pas compte des réponses ou du moins ne dise pas ce qui va ou ne va pas dans ce qui est proposé...

Maintenant je suppose que l'incident est clos, si vous voulez continuer de parler du probleme non technique de courtoisie veuillez m'envoyer un message privé, car celà polue innutilement le forum et n'interresse personne ici bas.

Citation:
Envoyé par frantzgac
Je demande à la cantonnade s'il est possible de faire un update avec jointure sur 2 tables avec Interbase et il est possible que vous n'ayez pas la réponse, inutile de s'en prendre les uns aux autres.
La réponse a déjà été donné précédemment...
NON, car la commande que vous avez donné ne fait pas parti de la norme SQL, elle est ppeut etre implémenté dans Sybase mais pas dans interbase/firebird.

Citation:
Envoyé par frantzgac
Dire que ceci

update client contrimm
set client.type_client=contrimm.type_client
where client.code_client=contrimm.code_client

est équivalent à cela

update client
set client.type_client = client.type_client

me parait polémique et non technique.
Il serait bon que vous utilisez les balises code lorsque vous ecrivez du code pour améliorer la lisibilité. Comme je vous l'ai déjà signalé dans votre premier message que j'ai du éditer. Mais vous persistez soit à m'ignorer soit à lire.

En ce qui concerne les deux ordres SQL, ils sont bien equivallents, c'est la triste vérité, si vous ne le comprennez pas, demandez pourquoi ils sont equivallents plutot que de dire que c'est faux...

Il ne faudrait pas inverser les roles, c'est vous qui avez un probleme, et qui posez des questions.
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/12/2004, 01h55   #15
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
Inverser les rôles c'est vide dit et crée un présupposé sur nos rôles respectifs que je ne suis pas certain d'agréer. Jusqu'à preuve du contraire, nous sommes égaux.

Je pose en effet des questions, mais je ne lis que des critiques sur ma formulation et non des réponses aux questions posées. C'est une méthode hélàs courante quand on a pas la réponse de dire que la question est mal posée.

J'ai résolu mon problème mais je reste curieux de savoir si j'aurais pu faire autrement et par conséquent en effet j'attends que vous
m'expliquiez en quoi

update client contrimm
set client.type_client=contrimm.type_client
where client.code_client=contrimm.code_client

est équivalent à cela

update client
set client.type_client = client.type_client
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/12/2004, 11h56   #16
Membre actif
 
Avatar de Superstivix
 
Inscription : décembre 2003
Messages : 250
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 250
Points : 199
Points : 199
Envoyer un message via MSN à Superstivix
bonjour,

votre question porte sur ce code qui ne me parait pas non plus (comme mon collègue) respecter le standard SQL!

Code :
1
2
3
4
UPDATE client
SET 	a.type_client	=	b.type_client
FROM client a,vs_contrimm b
WHERE a.code_client=b.code_client
Je travaille sur MS_SQL et la requete se rapprochant le plus à la votre est la suivante:

Code :
1
2
3
4
UPDATE client
SET              type_client = vs_contrimm.type_client
FROM         vs_contrimm
WHERE     client.CLE = vs_contrimm.CLE
Cette requete fonctionne très bien sous SQL_server, essayez là sous Interbase!

En espérant vous avoir aidé

Cordialement
Superstivix
__________________
Modérateur Taverne et C++Builder
Règles du Club - Règles de la Taverne
FAQ BCB - sources
Et je mords
Superstivix est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/12/2004, 12h23   #17
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Hélas comme je l'ai déjà signalé (en donnant le seul moyen SQL accepté par interbase pour ce type de mise à jour) on ne peux pas faire ça avec interbase.

La solution est celle que j'ai donnée, c'est à dire d'utiliser un sous-select.
Mais ce n'est pas l'avis de tous apparemment
Sinon il y a aussi la solution de le faire via une procédure stoquée, mais ce n'est pas ce qui est demandé ici.

Par contre sous MS_server que fait cet ordre dans le cas ou dans vs_contrimm il y a plusieurs enregistrements correspondant à une CLE client ? Une erreur ? Si non quel enregistrement est pris en compte pour le mise à jour ?
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/12/2004, 14h27   #18
Membre actif
 
Avatar de Superstivix
 
Inscription : décembre 2003
Messages : 250
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 250
Points : 199
Points : 199
Envoyer un message via MSN à Superstivix
Citation:
Envoyé par Barbibulle
Par contre sous MS_server que fait cet ordre dans le cas ou dans vs_contrimm il y a plusieurs enregistrements correspondant à une CLE client ? Une erreur ? Si non quel enregistrement est pris en compte pour le mise à jour ?
Non pas d'erreur, l'update s'effectue correctement!
L'enregistrement pris pour la mise à jour est le dernier trouvé lorsqu'on fait un SELECT * FROM vs_contrimm.
__________________
Modérateur Taverne et C++Builder
Règles du Club - Règles de la Taverne
FAQ BCB - sources
Et je mords
Superstivix est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/12/2004, 14h39   #19
Membre Expert
 
Avatar de Barbibulle
 
Frédéric
Inscription : octobre 2002
Messages : 1 722
Détails du profil
Informations personnelles :
Nom : Frédéric
Âge : 42

Informations forums :
Inscription : octobre 2002
Messages : 1 722
Points : 2 025
Points : 2 025
Donc c'est à utiliser en connaissance de cause.

S'il n'y a pas d'erreur c'est qu'il fait bien une jointure et il doit faire un UPDATE par ligne jointe.

Ce qui veux dire que si une cle cliente à 100 000 référence dans vs_contrimm il y aura 100 000 update sur le même client (s'écrasant la même valeur à chaque fois)

Il ne me semble pas que cette syntaxe fasse partie d'une des normes SQL. Mais je me trompe peut être.

Ce qui est certain c'est que ce n'est pas implémenté dans Interbase.
Barbibulle est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/12/2004, 15h21   #20
Membre du Club
 
Inscription : juillet 2004
Messages : 200
Détails du profil
Informations forums :
Inscription : juillet 2004
Messages : 200
Points : 67
Points : 67
Par défaut pas de doublon

Inutile d'épiloguer sur des doublons dans la table contrimm de l'exemple, il n'y en a pas.

J'ai repris des tests et j'ai effectivement constaté que la syntaxe utilisant le sous select fonctionne. J'avais fait erreur dans la modification du copier-coller.

Il n'y a en effet pas de clause FROM dans l'UPDATE d'Interbase (langref.pdf) mais l'évocation d'une table dans le sous select permet de faire une jointure avec celle citée dans l'Update.

Milles excuses Barbibulle.
frantzgac est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



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


 
 
 
 
Partenaires

Hébergement Web