Colonne inconnue dans la clause Where


126

J'ai une question simple:

SELECT u_name AS user_name FROM users WHERE user_name = "john";

Je reçois Unknown Column 'user_name' in where clause. Puis-je ne pas me référer à 'user_name'd'autres parties de la déclaration même après select 'u_name as user_name'?

Réponses:


94

SQL est évalué à l'envers, de droite à gauche. Ainsi, la clause where est analysée et évaluée avant la clause select. Pour cette raison, l'alias de u_name en user_name n'a pas encore eu lieu.


30
Plutôt que «à l'envers», je pense qu'il est plus logique de dire «à l'envers»
Joe Phillips

4
Il est plus logique de dire que la déclaration entière est analysée, transformée et optimisée dans son ensemble dans un processus complexe en plusieurs étapes. "SQL est évalué à l'envers, de droite à gauche" est tout simplement faux
David Aldridge

3
réponse incomplète car l'utilisateur a demandé si 'user_name' peut être utilisé dans la déclaration, ce qu'il peut être après par exemple 'HAVING'
luke_mclachlan

45

Qu'en est-il de:

SELECT u_name AS user_name FROM users HAVING user_name = "john";

16
Pourquoi utiliseriez-vous à la HAVINGplace de WHEREdans ce cas?
PeteGO

4
@PeteGO se réfère à la réponse de Paul Dixon. tldr; HAVING est évalué plus tard que WHERE et, plus important encore, SELECT.
jairbow

38

Consultez la page de manuel MySQL suivante: http://dev.mysql.com/doc/refman/5.0/en/select.html

«Un alias peut être attribué à une exp_sélection en utilisant AS nom_alias. L'alias est utilisé comme nom de colonne de l'expression et peut être utilisé dans les clauses GROUP BY, ORDER BY ou HAVING.»

(...)

Il n'est pas permis de faire référence à un alias de colonne dans une clause WHERE, car la valeur de la colonne peut ne pas encore être déterminée lorsque la clause WHERE est exécutée. Voir Section B.5.4.4, «Problèmes avec les alias de colonne».


Notez également (de l'homme MySQL): Le standard SQL exige que HAVING ne fasse référence qu'aux colonnes de la clause GROUP BY ou aux colonnes utilisées dans les fonctions d'agrégation. Cependant, MySQL prend en charge une extension de ce comportement et permet à HAVING de faire référence aux colonnes de la liste SELECT et aux colonnes des sous-requêtes externes également.
Vincent Pazeller du

12
select u_name as user_name from users where u_name = "john";

Pensez-y comme ceci, votre clause where est évaluée en premier, pour déterminer quelles lignes (ou lignes jointes) doivent être renvoyées. Une fois la clause where exécutée, la clause select s'exécute pour elle.

Pour mieux dire, imaginez ceci:

select distinct(u_name) as user_name from users where u_name = "john";

Vous ne pouvez pas faire référence à la première moitié sans la seconde. Où est toujours évalué en premier, puis la clause select.


11

Si vous essayez d'effectuer une requête comme celle-ci (recherchez tous les nœuds avec au moins une pièce jointe) où vous avez utilisé une instruction SELECT pour créer un nouveau champ qui n'existe pas réellement dans la base de données, et essayez d'utiliser l'alias pour ce résultat, vous rencontrerez le même problème:

SELECT nodes.*, (SELECT (COUNT(*) FROM attachments 
WHERE attachments.nodeid = nodes.id) AS attachmentcount 
FROM nodes
WHERE attachmentcount > 0;

Vous obtiendrez une erreur "Colonne inconnue 'attachmentcount' dans la clause WHERE".

La solution est en fait assez simple - remplacez simplement l'alias par l'instruction qui produit l'alias, par exemple:

SELECT nodes.*, (SELECT (COUNT(*) FROM attachments 
WHERE attachments.nodeid = nodes.id) AS attachmentcount 
FROM nodes 
WHERE (SELECT (COUNT(*) FROM attachments WHERE attachments.nodeid = nodes.id) > 0;

Vous obtiendrez toujours l'alias renvoyé, mais maintenant SQL ne devrait pas s'embarrasser de l'alias inconnu.


1
J'étais confronté à ce problème exact et je suis tombé sur votre réponse - merci! Juste pour noter, il est (naturellement) un peu lent sur les grandes bases de données, mais je suis quand même confronté à une configuration de base de données héritée stupide.
Liam Newmarch

Je crois que vous avez un supplément (dans votre requête avant le (COUNT(*)qui n'est fermé nulle part.
tftd

3
Mais l'instruction SELECT n'est-elle pas exécutée deux fois?
Matej

Je ne suis de loin pas un expert mysql mais cela semble très inperformat. J'ai constaté que les sélections imbriquées rendent une requête beaucoup plus lente.
GDY

8

Votre définition aliasn'est pas accueillie par la WHEREclause que vous devez utiliser la HAVINGclause pour cela

SELECT u_name AS user_name FROM users HAVING user_name = "john";

OU vous pouvez utiliser directement le nom de la colonne d'origine avec le WHERE

SELECT u_name AS user_name FROM users WHERE u_name = "john";

Comme vous avez le résultat dans un alias défini par l'utilisateur à la suite d'une sous-requête ou de tout calcul, il sera accessible par la HAVINGclause et non par leWHERE

SELECT u_name AS user_name ,
(SELECT last_name FROM users2 WHERE id=users.id) as user_last_name
FROM users  WHERE u_name = "john" HAVING user_last_name ='smith'

7

Soit:

SELECT u_name AS user_name
FROM   users
WHERE  u_name = "john";

ou:

SELECT user_name
from
(
SELECT u_name AS user_name
FROM   users
)
WHERE  u_name = "john";

Ce dernier devrait être le même que le premier si le SGBDR prend en charge la poussée de prédicat dans la vue en ligne.



5

Non, vous devez le sélectionner avec le nom correct. Si vous avez donné la table que vous sélectionnez à partir d'un alias, vous pouvez l'utiliser.



1

Colonne inconnue dans la WHEREclause causée par les lignes 1 et 2 et résolue par la ligne 3:

  1. $sql = "SELECT * FROM users WHERE username =".$userName;
  2. $sql = "SELECT * FROM users WHERE username =".$userName."";
  3. $sql = "SELECT * FROM users WHERE username ='".$userName."'";

Qu'avez-vous changé et pourquoi? De plus, pourquoi avez-vous publié du code largement ouvert aux injections SQL?
Nico Haase

1

Peut-être que cela aide.

Vous pouvez

SET @somevar := '';
SELECT @somevar AS user_name FROM users WHERE (@somevar := `u_name`) = "john";

Ça marche.

MAIS ASSUREZ-VOUS DE CE QUE VOUS FAITES!

  • Les index ne sont PAS UTILISÉS ici
  • Une table complète sera scannée - vous n'avez pas spécifié la partie LIMIT 1
  • Donc, - CETTE QUESTION SERA SLLLOOOOOOW sur d'énormes tables.

Mais, peut-être que cela aide dans certains cas


0

Alors que vous pouvez alias vos tables dans votre requête (par exemple, "SELECT u.username FROM users u;"), vous devez utiliser les noms réels des colonnes que vous référencez. AS affecte uniquement la manière dont les champs sont renvoyés.


Je pense que vous pouvez utiliser l'alias dans certains SGBDR comme MySql par exemple. Vous avez cependant raison pour Sql Server.
PeteGO

0
SELECT user_name
FROM
(
SELECT name AS user_name
FROM   users
) AS test
WHERE  user_name = "john"

Pourquoi voudriez-vous utiliser une sous-requête? Beaucoup plus simple sans.
PeteGO

0

J'ai juste eu ce problème.

Assurez-vous qu'il n'y a pas d'espace dans le nom de l'entité dans la base de données.

par exemple 'nom_utilisateur' au lieu de 'nom_utilisateur'


-1

essayez votre tâche en utilisant la condition IN ou la condition OR et cette requête fonctionne également sur spark-1.6.x

 SELECT  patient, patient_id FROM `patient` WHERE patient IN ('User4', 'User3');

ou

SELECT  patient, patient_id FROM `patient` WHERE patient = 'User1' OR patient = 'User2';

-1

Pour moi, la racine du problème était un nombre que j'ai copié pour l'utiliser dans une clause WHERE. Le numéro avait un symbole «invisible», du moins pour MySQL Workbench. J'ai placé le numéro dans la console Chrome, il était clairement visible.


-2

J'ai eu le même problème, j'ai trouvé cela utile.

mysql_query("SELECT * FROM `users` WHERE `user_name`='$user'");

n'oubliez pas de mettre $ user entre '' guillemets simples.


1
Ce code est largement ouvert à l'injection SQL. Personne ne devrait utiliser ce code pour résoudre le problème donné
Nico Haase
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.