Nieznana kolumna w klauzuli gdzie


126

Mam proste zapytanie:

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

Rozumiem Unknown Column 'user_name' in where clause. Czy nie mogę odnieść się do 'user_name'innych części oświadczenia nawet po select 'u_name as user_name'?

Odpowiedzi:


94

SQL jest oceniany wstecz, od prawej do lewej. Zatem klauzula where jest analizowana i szacowana przed klauzulą ​​select. Z tego powodu aliasowanie nazwy u_nazwa_użytkownika jeszcze nie nastąpiło.


30
Myślę, że bardziej sensowne jest powiedzenie „na lewą stronę” niż „wstecz”
Joe Phillips

4
Bardziej sensowne jest stwierdzenie, że cała instrukcja jest analizowana, przekształcana i optymalizowana jako całość w złożonym, wieloetapowym procesie. „SQL jest oceniany wstecz, od prawej do lewej” jest po prostu błędne
David Aldridge,

3
niepełna odpowiedź, ponieważ użytkownik zapytał, czy w instrukcji można użyć wyrażenia „nazwa_użytkownika”, co może być np. po „HAVING”
luke_mclachlan

45

Co powiesz na:

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

16
Dlaczego miałbyś używać HAVINGzamiast WHEREw tym przypadku?
PeteGO

4
@PeteGO odnoszą się do odpowiedzi Paula Dixona. tldr; HAVING jest oceniana później niż WHERE i, co ważniejsze, SELECT.
jairbow

38

Zobacz następującą stronę podręcznika MySQL: http://dev.mysql.com/doc/refman/5.0/en/select.html

„Select_expr można nadać alias za pomocą AS alias_name. Alias ​​jest używany jako nazwa kolumny wyrażenia i może być używany w klauzulach GROUP BY, ORDER BY lub HAVING.”

(...)

Niedopuszczalne jest odwoływanie się do aliasu kolumny w klauzuli WHERE, ponieważ wartość kolumny może nie zostać jeszcze określona podczas wykonywania klauzuli WHERE. Zobacz Sekcja B.5.4.4, „Problemy z aliasami kolumn”.


Uwaga (od człowieka MySQL): Standard SQL wymaga, aby HAVING odnosiło się tylko do kolumn w klauzuli GROUP BY lub kolumn używanych w funkcjach agregujących. Jednak MySQL obsługuje rozszerzenie tego zachowania i pozwala MIEĆ odwoływanie się do kolumn na liście WYBIERZ, a także do kolumn w zewnętrznych podzapytaniach.
Vincent Pazeller

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

Pomyśl o tym w ten sposób, Twoja klauzula where jest obliczana jako pierwsza, aby określić, które wiersze (lub połączone wiersze) mają zostać zwrócone. Po wykonaniu klauzuli where, klauzula select jest uruchamiana dla niej.

Ujmując to lepiej, wyobraź sobie to:

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

Nie możesz odwołać się do pierwszej połowy bez drugiej. Gdzie zawsze jest oceniany jako pierwszy, a następnie klauzula select.


11

Jeśli próbujesz wykonać zapytanie podobne do poniższego (znajdź wszystkie węzły z co najmniej jednym załącznikiem), w którym użyłeś instrukcji SELECT, aby utworzyć nowe pole, które faktycznie nie istnieje w bazie danych, i spróbuj użyć alias dla tego wyniku napotkasz ten sam problem:

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

W klauzuli WHERE pojawi się błąd „Nieznana kolumna„ filecount ””.

Rozwiązanie jest właściwie dość proste - wystarczy zamienić alias na instrukcję, która tworzy alias, np .:

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;

Nadal otrzymasz zwrócony alias, ale teraz SQL nie powinien działać na nieznanym aliasie.


1
Miałem dokładnie ten problem i znalazłem twoją odpowiedź - dziękuję! Warto zauważyć, że jest to (co zrozumiałe) trochę powolne w przypadku dużych baz danych, ale i tak mam do czynienia z głupią konfiguracją dziedziczonej bazy danych.
Liam Newmarch

Wydaje mi się, że masz (w zapytaniu dodatek, (COUNT(*)który nie jest nigdzie zamknięty.
tftd

3
Ale czy instrukcja SELECT nie jest uruchamiana dwukrotnie?
Matej

Zdecydowanie nie jestem ekspertem od mysql, ale wydaje się to bardzo nieefektywne. Doświadczyłem, że zagnieżdżone selekcje znacznie spowalniają zapytanie.
GDY

8

Zdefiniowane aliasprzez WHERECiebie nie są mile widziane przez klauzulę, w której musisz użyć HAVINGklauzuli

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

LUB możesz bezpośrednio użyć oryginalnej nazwy kolumny z rozszerzeniem WHERE

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

Tak samo, jak w przypadku wyniku w aliasie zdefiniowanym przez użytkownika w wyniku podzapytania lub dowolnego obliczenia, dostęp do niego będzie możliwy przez HAVINGklauzulę, a nie przezWHERE

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

Zarówno:

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

lub:

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

Ten drugi powinien być taki sam jak pierwszy, jeśli RDBMS obsługuje wypychanie predykatów do widoku in-line.





1

Nieznana kolumna w WHEREklauzuli spowodowana liniami 1 i 2 i rozwiązana przez linię 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."'";

Co zmieniłeś i dlaczego? Ponadto, dlaczego wysłałeś kod, który jest szeroko otwarty na iniekcje SQL?
Nico Haase

1

Może to pomoże.

Możesz

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

To działa.

ALE UPEWNIJ SIĘ, CO ROBISZ!

  • Indeksy NIE SĄ UŻYWANE tutaj
  • Zostanie zeskanowana PEŁNA TABELA - nie określiłeś części LIMIT 1
  • A więc - TO ZAPYTANIE BĘDZIE WYGLĄDAŁO NA DUŻYCH stołach.

Ale może w niektórych przypadkach to pomaga


0

Chociaż możesz aliasować swoje tabele w zapytaniu (np. „SELECT u.username FROM users u;”), musisz użyć rzeczywistych nazw kolumn, do których się odnosisz. AS wpływa tylko na sposób zwracania pól.


Myślę, że możesz użyć aliasu w niektórych RDBMS, takich jak na przykład MySql. Masz jednak rację dla Sql Server.
PeteGO

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

Dlaczego chcesz użyć zapytania podrzędnego? O wiele prostsze bez.
PeteGO

0

Właśnie miałem ten problem.

Upewnij się, że w nazwie jednostki w bazie danych nie ma spacji.

np. „nazwa_użytkownika” zamiast „nazwa_użytkownika”


-1

wypróbuj swoje zadanie używając warunku IN lub warunku OR , a także to zapytanie działa na spark-1.6.x

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

lub

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

-1

Dla mnie źródłem problemu była liczba, którą skopiowałem, aby użyć w klauzuli WHERE. Liczba miała symbol „niewidoczny”, przynajmniej dla MySQL Workbench. Numer umieściłem w konsoli Chrome, żeby był dobrze widoczny.


-2

Miałem ten sam problem, uznałem to za przydatne.

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

pamiętaj, aby umieścić $ user w pojedynczych cudzysłowach.


1
Ten kod jest szeroko otwarty do iniekcji SQL. Nikt nie powinien używać tego kodu do rozwiązania danego problemu
Nico Haase
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.