76 votes

Comment résoudre les noms de colonne ambigus lors de la récupération des résultats ?

J'ai deux tables dans ma base de données :

Tableau de nouvelles avec des colonnes :

  • id - l'identifiant de la nouvelle
  • user - l'identifiant de l'auteur)

Table USERS avec des colonnes :

  • id - l'identifiant de l'utilisateur

Je veux exécuter ce SQL :

SELECT * FROM news JOIN users ON news.user = user.id 

Lorsque j'obtiens les résultats en PHP, j'aimerais obtenir un tableau associatif et obtenir les noms des colonnes par $row['column-name'] . Comment puis-je obtenir l'ID de la nouvelle et l'ID de l'utilisateur, ayant le même nom de colonne ?

119voto

CMS Points 315406

Vous pouvez définir des alias pour les colonnes que vous sélectionnez :

$query = 'SELECT news.id AS newsId, user.id AS userId, [OTHER FIELDS HERE] FROM news JOIN users ON news.user = user.id'

1 votes

Cette réponse a rendu les réponses à stackoverflow.com/questions/9233387/sql-should-i-use-a-join travailler pour moi, merci !

3 votes

Le principal inconvénient de cette approche est que, contrairement aux SELECT * En effet, la requête est étroitement liée à la structure de la table. Autrement dit, chaque fois que vous ajoutez/supprimez/renommez des colonnes dans le schéma, vous devez modifier votre requête en conséquence.

4 votes

@RonInbar. SELECT * est un cauchemar de maintenance dans les grands systèmes. Vous suggérez que l'ajout d'une colonne est simple et ne nécessite aucune modification de SQL si l'on utilise SELECT * Cependant, ce n'est pas le cas pour le problème d'aliasing identifié ici. Cela peut également avoir un impact inutile sur les performances si le nouveau champ est grand. Il peut aussi casser les contrôles côté client qui attendent un certain nombre de champs. Je pourrais continuer, mais les avantages de SELECT * disparaissent très vite quand on comprend l'impact qu'elles ont sur la maintenabilité et les performances.

43voto

Greg Points 132247

Vous pouvez soit utiliser les indices numériques ( $row[0] ) ou mieux, utilisez AS dans le MySQL :

SELECT *, user.id AS user_id FROM ...

13 votes

Notez également que si vous utilisez wildwarcd * il doit être le premier de la clause de sélection. NON : SELECT user_id,* ...

2 votes

C'est vrai mais tu peux toujours faire SELECT user.id AS user_id, user.* FROM ... si l'ordre est important.

24voto

Eab Points 61

Je viens de trouver ça. C'est probablement une mauvaise pratique mais ça a marché pour moi dans ce cas.

Je fais partie des personnes paresseuses qui ne veulent pas aliaser ou écrire chaque nom de colonne avec un préfixe de table.

Vous pouvez sélectionner toutes les colonnes d'une table spécifique à l'aide de la fonction table_name.* dans votre déclaration de sélection.

Lorsque vous avez des noms de colonnes dupliqués, mysql les écrase du premier au dernier. Les données du premier nom de colonne dupliqué seront écrasées lorsqu'il rencontrera à nouveau ce nom de colonne. Ainsi, le nom de colonne dupliqué qui arrive en dernier gagne.

Si je joins 3 tables, chacune contenant un nom de colonne dupliqué, l'ordre des tables dans l'instruction select déterminera les données que j'obtiendrai pour la colonne dupliquée.

Exemple :

SELECT table1.* , table2.* , table3.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup;

Dans l'exemple ci-dessus, la valeur de dup que j'obtiendrai sera de table3 .

Et si je veux dup pour être la valeur de table1 ?

Alors je dois faire ça :

SELECT table3.* , table2.* , table1.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup;

Maintenant, table1 vient en dernier, donc la valeur de dup sera la valeur du tableau 1.

J'ai obtenu le prix que je voulais pour dup sans avoir à écrire chaque colonne et j'ai toujours toutes les colonnes pour travailler. Hourra !

Je connais la valeur de dup devrait être le même dans les 3 tables, mais que faire si table3 n'a pas de valeur correspondante pour dup ? Alors dup serait vide dans le premier exemple, et ce serait une déception.

3 votes

S'appuyer sur des commandes non documentées qui fonctionnent pour l'instant et qui ne soulèveront aucune erreur si l'implémentation de la base de données change est une idée INCROYABLE.

2 votes

Le piratage de la commande est effrayant, mais +1 pour pouvoir sélectionner avec table.* pour que je puisse faire SELECT table1.*, table2.this_one_column_need FROM table1 INNER JOIN table2 ON... .

11voto

Dirk Points 1045

Un autre conseil : si vous voulez avoir un code PHP plus propre, vous pouvez créer un VIEW dans la base de données, par ex.

Par exemple :

CREATE VIEW view_news AS
SELECT
  news.id news_id,
  user.id user_id,
  user.name user_name,
  [ OTHER FIELDS ]
FROM news, users
WHERE news.user_id = user.id;

En PHP :

$sql = "SELECT * FROM view_news";

9voto

Paolo Bergantino Points 199336

Vous pouvez faire quelque chose comme

SELECT news.id as news_id, user.id as user_id ....

Et puis $row['news_id'] sera l'identifiant de la nouvelle et $row['user_id'] sera l'identifiant de l'utilisateur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X