Невідомий стовпець, де пункт


126

У мене простий запит:

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

Я отримую Unknown Column 'user_name' in where clause. Чи не можу я посилатися на 'user_name'інші частини заяви навіть після select 'u_name as user_name'?

Відповіді:


94

SQL оцінюється назад, справа наліво. Тож пункт де проаналізований і оцінюється до вибору. Через це дозволу u_name до user_name ще не відбулося.


30
Замість того, щоб "назад", я думаю, що має сенс сказати "зсередини"
Джо Філіпс,

4
Більше сенсу сказати, що весь вислів аналізується, трансформується та оптимізується в цілому в складному багатоступеневому процесі. "SQL оцінюється назад, справа наліво" - це просто неправильно
Девід Олдрідж

3
неповна відповідь, оскільки користувач запитав, чи може в заяві вживатися "ім'я користувача", яке може бути після напр. "HAVING"
luke_mclachlan

45

А як на рахунок:

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

16
Чому б ви використовували HAVINGзамість WHEREцього випадку?
PeteGO

4
@ PeteGO посилаються на відповідь Пола Діксона. tldr; ХАРЧУВАННЯ оцінюється пізніше, де БЕЗ, і, що ще важливіше, ВИБІР.
jairbow

38

Дивіться таку сторінку керівництва MySQL: http://dev.mysql.com/doc/refman/5.0/en/select.html

"Вибраному_expr можна надати псевдонім, використовуючи AS alias_name. Псевдонім використовується як ім'я стовпця виразу і може бути використаний у пунктах GROUP BY, ORDER BY або HAVING."

(...)

Неприпустимо посилатися на псевдонім стовпця в пункті WHERE, оскільки значення стовпця ще не може бути визначене при виконанні пропозиції WHERE. Див. Розділ B.5.4.4, «Проблеми з псевдонімом стовпців».


Також зверніть увагу (від людини MySQL): Стандарт SQL вимагає, щоб HAVING повинен посилатися лише на стовпці в пункті GROUP BY або стовпці, що використовуються в сукупності функцій. Однак MySQL підтримує розширення до цієї поведінки і дозволяє HAVING посилатися на стовпці у списку SELECT та стовпці у зовнішніх підзапитах.
Вінсент Пазеллер

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

Подумайте про це так: ваш пункт де оцінюється спочатку, щоб визначити, які рядки (або об'єднані рядки) потрібно повернути. Після того, як виконується пропозиція де, за цим пунктом виконується пункт select.

Якщо говорити краще, уявіть собі це:

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

Ви не можете посилатися на перший тайм без другого. Там, де завжди спочатку оцінюється, тоді пункт вибору.


11

Якщо ви намагаєтеся виконати такий запит, як наступний (знайдіть усі вузли принаймні з одним вкладенням), де ви використовували оператор SELECT для створення нового поля, яке фактично не існує в базі даних, і спробуйте використовувати псевдонім для цього результату ви зіткнетеся з тією ж проблемою:

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

Ви отримаєте помилку "Невідомий стовпець" додаток "у пункті WHERE".

Рішення насправді досить просте - просто замініть псевдонім на заяву, яка створює псевдонім, наприклад:

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;

Ви все одно отримаєте повернення псевдоніму, але тепер SQL не повинен працювати на невідомий псевдонім.


1
Я зіткнувся з цією точною проблемою і натрапив на вашу відповідь - дякую! Зауважимо, на великих базах даних це (зрозуміло) трохи повільно, але я все одно маю справу з дурною спадковою установкою бази даних.
Ліам Ньюмарш

Я вважаю, у вас є додатковий (запит, перед (COUNT(*)яким не закривається ніде.
tftd

3
Але чи не запускається оператор SELECT двічі?
Матей

Я далеко не експерт по mysql, але це здається дуже недосконалим. Я відчував, що вкладені вибір робить запит набагато повільніше.
GDY

8

Ваша визначена aliasпозиція не вітається WHEREпунктом, який ви повинні використовувати HAVINGдля цього

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

АБО ви можете безпосередньо використовувати оригінальну назву стовпця за допомогою WHERE

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

Те саме, що у вас є результат у визначеному користувачем псевдонімі в результаті підзапиту або будь-якого обчислення, до нього буде доступно HAVINGпункт, а неWHERE

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

Або:

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

або:

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

Останні повинні бути такими ж, як і перші, якщо RDBMS підтримує натискання предикатами на внутрішній вигляд.



5

Не потрібно вибирати його з правильною назвою. Якщо ви дали таблицю, яку ви вибрали з псевдоніма, ви можете скористатися цим.



1

Невідомий стовпець у WHEREпункті, викликаний рядками 1 та 2 та вирішений рядком 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."'";

Що ви змінили і чому? Крім того, чому ви розмістили код, широко відкритий для ін'єкцій SQL?
Ніко Хааз

1

Можливо, це допоможе.

Ти можеш

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

Це працює.

АЛЕ ПЕРЕГОЛУЙТЕ ТАКОЖ, ЩО РОБИТИ!

  • Тут не використовуються індекси
  • Буде відскановано ПОЛУ ТАБЛИЦЮ - ви не вказали обмеження 1 частини
  • Отже, - ЦЕ ЗАПИТАННЯ БУДЕ СЛУЧАЄМО на величезних столах.

Але, може, це допомагає в деяких випадках


0

Хоча ви можете псевдоніми ваших таблиць у вашому запиті (наприклад, "SELECT u.username FROM users u;"), ви повинні використовувати фактичні назви стовпців, на які ви посилаєтесь. AS впливає лише на те, як повертаються поля.


Я думаю, ви можете використовувати псевдонім у деяких RDBMS, таких як MySql, наприклад. Ти правда для сервера Sql.
PeteGO

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

Чому ви хочете використовувати підзапит? Набагато простіше без.
PeteGO

0

Просто була ця проблема.

Переконайтесь, що в базі даних немає місця в назві об'єкта.

наприклад, "ім'я користувача" замість "ім'я користувача"


-1

спробуйте своє завдання, використовуючи умову IN або АБО, а також цей запит працює на spark-1.6.x

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

або

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

-1

Для мене коренем проблеми було число, яке я скопіював для використання в пункті WHERE. Цифра мала символ "невидимий", принаймні для MySQL Workbench. Я помістив номер у консолі Chrome, це було добре видно.


-2

У мене була така ж проблема, я вважав це корисним.

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

не забудьте поставити $ user у "" котирування.


1
Цей код широко відкритий для ін'єкції SQL. Ніхто не повинен використовувати цей код для вирішення заданої проблеми
Ніко Хааз
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.