Unbekannte Spalte in Where-Klausel


126

Ich habe eine einfache Frage:

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

Ich verstehe Unknown Column 'user_name' in where clause. Kann ich mich auch danach nicht auf 'user_name'andere Teile der Erklärung beziehen select 'u_name as user_name'?

Antworten:


94

SQL wird von rechts nach links rückwärts ausgewertet. Daher wird die where-Klausel vor der select-Klausel analysiert und ausgewertet. Aus diesem Grund ist das Aliasing von u_name zu user_name noch nicht aufgetreten.


30
Anstatt "rückwärts" zu sein, halte ich es für sinnvoller, "von innen nach außen" zu sagen
Joe Phillips

4
Es ist sinnvoller zu sagen, dass die gesamte Anweisung in einem komplexen, mehrstufigen Prozess als Ganzes analysiert, transformiert und optimiert wird. "SQL wird rückwärts von rechts nach links ausgewertet" ist einfach falsch
David Aldridge

3
unvollständige Antwort, als der Benutzer fragte, ob 'Benutzername' in der Anweisung verwendet werden kann, was zB nach 'HAVING'
luke_mclachlan

45

Wie wäre es mit:

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

16
Warum würden Sie HAVINGstatt WHEREin diesem Fall verwenden?
PeteGO

4
@PeteGO beziehen sich auf die Antwort von Paul Dixon. tldr; HAVING wird später als WHERE ausgewertet und, was noch wichtiger ist, SELECT.
Jairbow

38

Siehe die folgende MySQL-Handbuchseite: http://dev.mysql.com/doc/refman/5.0/de/select.html

"Ein select_expr kann mit AS alias_name einen Alias ​​erhalten. Der Alias ​​wird als Spaltenname des Ausdrucks verwendet und kann in GROUP BY-, ORDER BY- oder HAVING-Klauseln verwendet werden."

(...)

Es ist nicht zulässig, in einer WHERE-Klausel auf einen Spaltenalias zu verweisen, da der Spaltenwert bei der Ausführung der WHERE-Klausel möglicherweise noch nicht ermittelt wurde. Siehe Abschnitt B.5.4.4, „Probleme mit Spaltenaliasen“.


Beachten Sie auch (vom MySQL-Mann): Der SQL-Standard verlangt, dass HAVING nur auf Spalten in der GROUP BY-Klausel oder auf Spalten verweisen darf, die in Aggregatfunktionen verwendet werden. MySQL unterstützt jedoch eine Erweiterung dieses Verhaltens und ermöglicht es HAVING, auf Spalten in der SELECT-Liste und Spalten in äußeren Unterabfragen zu verweisen.
Vincent Pazeller

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

Stellen Sie sich das so vor: Ihre where-Klausel wird zuerst ausgewertet, um zu bestimmen, welche Zeilen (oder verknüpften Zeilen) zurückgegeben werden müssen. Sobald die where-Klausel ausgeführt wurde, wird die select-Klausel ausgeführt.

Um es besser auszudrücken, stellen Sie sich Folgendes vor:

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

Sie können die erste Hälfte nicht ohne die zweite referenzieren. Wo immer zuerst ausgewertet wird, dann die select-Klausel.


11

Wenn Sie versuchen, eine Abfrage wie die folgende durchzuführen (suchen Sie alle Knoten mit mindestens einem Anhang), bei der Sie eine SELECT-Anweisung verwendet haben, um ein neues Feld zu erstellen, das in der Datenbank nicht vorhanden ist, und versuchen Sie es zu verwenden Der Alias ​​für dieses Ergebnis wird auf dasselbe Problem stoßen:

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

Sie erhalten die Fehlermeldung "Unbekannte Spalte 'Anhangsanzahl' in WHERE-Klausel".

Die Lösung ist eigentlich ziemlich einfach - ersetzen Sie einfach den Alias ​​durch die Anweisung, die den Alias ​​erzeugt, z.

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;

Der Alias ​​wird weiterhin zurückgegeben, aber jetzt sollte SQL den unbekannten Alias ​​nicht mehr stören.


1
Ich war genau mit diesem Problem konfrontiert und bin auf Ihre Antwort gestoßen - danke! Nur zu beachten, es ist (verständlicherweise) bei großen Datenbanken etwas langsam, aber ich habe es trotzdem mit einem dummen geerbten Datenbank-Setup zu tun.
Liam Newmarch

Ich glaube, Sie haben ein Extra (in Ihrer Anfrage, bevor das (COUNT(*)nirgendwo geschlossen wird.
27.

3
Aber wird die SELECT-Anweisung nicht zweimal ausgeführt?
Matej

Ich bin bei weitem kein MySQL-Experte, aber das scheint sehr unperformant zu sein. Ich habe erfahren, dass verschachtelte Auswahlen eine Abfrage viel langsamer machen.
GDY

8

Ihr definiert aliaswerden nicht durch die begrüßt WHEREKlausel haben Sie die verwenden HAVINGKlausel für diese

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

ODER Sie können den ursprünglichen Spaltennamen direkt mit dem verwenden WHERE

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

Genauso wie Sie das Ergebnis in einem benutzerdefinierten Alias ​​als Ergebnis einer Unterabfrage oder einer Berechnung haben, wird auf die HAVINGKlausel zugegriffen , nicht auf dieWHERE

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

Entweder:

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

oder:

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

Letzteres sollte mit Ersterem identisch sein, wenn das RDBMS das Verschieben von Prädikaten in die Inline-Ansicht unterstützt.



5

Nein, Sie müssen es mit dem richtigen Namen auswählen. Wenn Sie die Tabelle angegeben haben, die Sie aus einem Alias ​​ausgewählt haben, können Sie dies jedoch verwenden.



1

Unbekannte Spalte in WHEREKlausel, verursacht durch die Zeilen 1 und 2 und behoben durch Zeile 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."'";

Was hast du geändert und warum? Warum haben Sie außerdem Code veröffentlicht, der für SQL-Injektionen weit verbreitet ist?
Nico Haase

1

Vielleicht hilft es.

Sie können

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

Es klappt.

ABER STELLEN SIE SICHER, WAS SIE TUN!

  • Indizes werden hier NICHT VERWENDET
  • Es wird die VOLLSTÄNDIGE TABELLE gescannt - Sie haben den Teil LIMIT 1 nicht angegeben
  • Also, - DIESE FRAGE WIRD SLLLOOOOOOW auf riesigen Tischen sein.

Aber vielleicht hilft es in einigen Fällen


0

Während Sie Ihre Tabellen in Ihrer Abfrage aliasen können (dh "SELECT u.username FROM users u;"), müssen Sie die tatsächlichen Namen der Spalten verwenden, auf die Sie verweisen. AS wirkt sich nur darauf aus, wie die Felder zurückgegeben werden.


Ich denke, Sie können den Alias ​​in einigen RDBMS wie beispielsweise MySql verwenden. Sie sind jedoch korrekt für SQL Server.
PeteGO

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

Warum sollten Sie eine Unterabfrage verwenden? Viel einfacher ohne.
PeteGO

0

Hatte gerade dieses Problem.

Stellen Sie sicher, dass der Name der Entität in der Datenbank kein Leerzeichen enthält.

zB 'Benutzername' anstelle von 'Benutzername'


-1

Versuchen Sie Ihre Aufgabe mit der IN- Bedingung oder der OR- Bedingung, und auch diese Abfrage funktioniert mit spark-1.6.x

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

oder

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

-1

Für mich war die Wurzel des Problems eine Zahl, die ich kopiert habe, um sie in einer WHERE-Klausel zu verwenden. Die Nummer hatte ein "unsichtbares" Symbol, zumindest für MySQL Workbench. Ich habe die Nummer in die Chrome-Konsole gestellt, sie war deutlich sichtbar.


-2

Ich hatte das gleiche Problem, ich fand das nützlich.

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

Denken Sie daran, $ user in einfache Anführungszeichen zu setzen.


1
Dieser Code ist für die SQL-Injection weit offen. Niemand sollte diesen Code verwenden, um das gegebene Problem zu lösen
Nico Haase
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.