Problème de clé étrangère [RESOLU] - SQL/NoSQL - Programmation
Marsh Posté le 11-06-2009 à 17:36:31
D'un coté le champ "statut" de ta table "utilisateur" est un varchar de longueur 25, et de l'autre le champ id_statut de ta table "statut" est un int de longueur 11.
Sachant que l'un est une clé étrangère de l'autre, tu n'as pas l'impression d'une petite incohérence là ?
Marsh Posté le 11-06-2009 à 17:39:31
Le problème est que la jointure est faîte sur des données qui ne sont pas de même type :
utilisateur.statut est un varchar2, alors que statut.id_statut est un entier. Il faudrait juste rajouter une fonction de conversion. En Oracle, on ferait WHERE utilisateur.statut = to_char(statut.id_statut); ou WHERE to_number(utilisateur.statut) = statut.id_statut;. Mais je ne connais pas la syntaxe MySQL par coeur.
Marsh Posté le 11-06-2009 à 17:40:43
olivthill a écrit : Le problème est que la jointure est faîte sur des données qui ne sont pas de même type : |
Il faudrait surtout qu'il mette les mêmes types sur les 2 champs !
Marsh Posté le 11-06-2009 à 18:51:19
Ah oui exact, je viens de rectifier ça. Par contre PhPMyadmin m'indique toujours 0 résultat.
Marsh Posté le 11-06-2009 à 21:05:23
Et avec une jointure externe, tu obtiens des résultats ?
Marsh Posté le 11-06-2009 à 21:17:31
Je...sais pas faire de jointures externe
J'vais voir la tronche que ça a.
Marsh Posté le 11-06-2009 à 22:40:53
LEFT JOIN
D'ailleurs tu devrais employer la syntaxe INNER JOIN au lieu de faire des jointures "à l'ancienne" avec WHERE, c'est plus correct
Marsh Posté le 12-06-2009 à 10:47:18
Alors, j'ai essayé avec INNER JOIN et il m'envoie sur les roses, j'ai aussi essayé en changeant le moteur MyISAM par InnoDB mais rien n'y fait.
Par contre j'ai pas essayé avec LEFT JOIN.
Marsh Posté le 12-06-2009 à 11:22:36
Comment ça le "INNER JOIN m'envoie sur les roses" ? C'est quoi le message d'erreur ? Tu as utilisé la bonne syntaxe ?
Code :
|
ça donne quoi ?
Marsh Posté le 12-06-2009 à 11:30:24
Ah ça marche presque. En fait au lieu de m'afficher nom_util et prenom_util ça me met des NULL (alors que c'est rempli pourtant), en revanche l'intitule s'affiche bien.
Marsh Posté le 12-06-2009 à 11:35:10
Oui mais c'est normal que ça mette des NULL, le LEFT JOIN affiche toutes les données de la table de gauche (donc la table statut dans ton cas), même si elles ne sont pas remplies, alors que le INNER n'affiche que les données existantes. Je te l'ai fait faire pour justement vérifier si ta table comportait des données.
Donc si tu as des NULL, ça veut dire que ta table statut ne contient rien du tout par rapport à ton critère de jointure... Et c'est pour ça que ton INNER JOIN foire.
Marsh Posté le 12-06-2009 à 15:57:28
J'ai encore un peu de mal avec cette nouvelle syntaxe puisque au lycée on nous apprends a travailler uniquement avec le WHERE.
Et j'ai bien regardé le nom de mes champs et leu contenu et rien n'est vide, comment ça se fait
Marsh Posté le 12-06-2009 à 16:13:43
Et bien ton lycée à tout faux !
Le WHERE sert à filtrer une requête, pas à faire une jointure. Il faut savoir que cette syntaxe date de 1986, il serait temps d'évoluer.
L'avantage de la syntaxe avec INNER est multiple :
- ça permet de bien distinguer la partie de la requête qui concerne la jointure de la partie qui fait partie du filtre. Quand tu as une grosse requête sur plusieurs tables avec plein de clauses WHERE, ça devient vite chiant de décortiquer la requête pour trouver les WHERE qui concernent la jointure et les WHERE qui font partie du filtre. Avec JOIN, pas d'ambiguité possible
- imagine la requête suivante :
Code :
|
Maintenant, tu te rends compte que ta requête ne donne pas les résultats escomptés. Tu choisis de débugger en virant une clause WHERE. Mais tu te plantes et tu vires la ligne "AND tata.id = tutu.id".
Résultat : plus de jointure entre tata et tutu. Tu lances ta requête, et comme il n'y a plus de jointure entre ces tables, tu te retrouves avec un produit cartésien entre tata et tutu, qui peut mettre ton serveur à genoux si ces tables contiennent plusieurs milliers d'enregistrements.
Le WHERE pour les jointures, c'est le mal. Les profs qui enseignent ça devraient bruler en enfer.
Quant à ton problème, difficile de t'aider sans la base sous les yeux.
Marsh Posté le 12-06-2009 à 16:35:03
Merci pour l'exemple, ça permet en effet de mieux se rendre compte, et je maintiens que notre prof de SQL ne nous a jamais mentionné l'existence de INNER et LEFT JOIN
Sinon pour mon soucis tout est réglé Il y avait une mauvaise incrémentation d'un champ ce qui faisait tout capoter
Encore merci pour le coup de main et la leçon sur le INNER
Marsh Posté le 16-06-2009 à 10:54:41
Un ptit up pour une nouvelle question
J'ai deux tables Materiel(id_materiel, etat_materiel) et une table Type(id_type, type_machine, marque, #num_mat)
J'aimerai afficher uniquement les machines qui sont de type 'ordinateur'. Donc je fais la requête suivante.
SELECT id_materiel,etat_materiel,marque,description_type
FROM materiel
LEFT JOIN type
ON type.num_mat = materiel.id_materiel
AND type_machine = 'ordinateur'
ORDER BY id_materiel;
Le problème c'est que la requête m'affiche quand même l'id_materiel et etat_materiel des machines qui ne sont pas des ordinateurs.
J'ai du mal à voir comment je pourrais corriger ça
Merci
Marsh Posté le 16-06-2009 à 11:01:05
ReplyMarsh Posté le 16-06-2009 à 11:04:39
Ah oui exact. Merci beaucoup.
Ça va finir par rentrer un jour, si si
Marsh Posté le 16-06-2009 à 11:05:36
Voilà, c'est exactement ce que je disais... A force de faire des jointures avec des WHERE, on finit par ne plus distinguer ce qui est jointure et ce qui est filtre... Les profs qui enseignent de cette façon méritent la peine de mort
Marsh Posté le 16-06-2009 à 11:20:05
Exactement, mauvaise habitude Mais bon je vais corriger ça, merci à vous deux
Marsh Posté le 17-06-2009 à 10:42:38
Deamon a écrit : WHERE type_machine = 'ordinateur' |
d'ailleurs, ça c'est un des points positifs d'ACCESS sur les autres SGBD : sur ce point il est bien plus rigoureux que les autres, puisqu'il plante si on met un filtre dans une clause "ON".
sympa pour prendre en main la syntaxe du coup
Marsh Posté le 11-06-2009 à 16:25:53
Bonjour ,
J'ai un problème avec une requête SQL. Je voudrais avoir un résultat qui nécessite de passer par 2 tables et donc d'avoir une clé étrangère.
Présentation de mes tables.
CREATE TABLE utilisateur
(
id_util int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
nom_util varchar(20) NOT NULL,
prenom_util varchar(20) NOT NULL,
login varchar(20) NOT NULL,
pass varchar(20) NOT NULL,
statut varchar(25) NOT NULL,
FOREIGN KEY (statut) REFERENCES statut (id_statut)
);
CREATE TABLE statut
(
id_statut int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
intitule_statut varchar(20) NOT NULL
);
Ma requête est toute simple
SELECT nom_util, prenom_util, intitule_statut
FROM statut, utilisateur
WHERE utilisateur.statut = statut.id_statut;
Quand je fais ça dans PhpMyAdmin la requête ne me renvois aucun résultat alors que ces colonnes sont remplis.
Y aurait-il une explication toute simple et logique à ce mystérieux problème qui m'empêche de dormir ?
Merci
Message édité par Profil supprimé le 16-06-2009 à 11:05:02