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'?

Btuman
quelle

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.

Dacracot
quelle
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";
Septimus
quelle
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“.

Paul Dixon
quelle
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.

Mark S.
quelle
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.

Jon
quelle
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'
M Khalid Junaid
quelle
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.

David Aldridge
quelle
6

korrigiert:

SELECT u_name AS user_name FROM users WHERE u_name = 'john';
Steven A. Lowe
quelle
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.

Per Hornshøj-Schierbeck
quelle
2

Nein, du kannst nicht. Benutzername ist erst nach der Rückgabe vorhanden.

Jarrett Meyer
quelle
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."'";
Oliyid
quelle
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

F_S
quelle
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.

Blumer
quelle
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"
Jason Plank
quelle
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'

user3103155
quelle
-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';
KARTHIKEYAN.A
quelle
-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.

Vi0nik
quelle
-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.

devWaleed
quelle
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