位置子句中的未知列


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'

Answers:


94

SQL从右到左向后评估。因此,where子句将在select子句之前进行解析和评估。因此,尚未发生u_name到user_name的别名。


30
而不是“倒退”我认为它更有意义说“内而外”
乔·菲利普斯

4
说整个语句在一个复杂的,多阶段的过程中作为一个整体进行解析,转换和优化是更有意义的。“ SQL从右到左向后评估”是错误的
David Aldridge

3
由于用户询问语句中是否可以使用“ user_name”,因此答案不完整,例如可以在“ HAVING”之后使用
luke_mclachlan

45

关于什么:

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

16
在这种情况下,为什么要使用HAVING而不是WHERE
PeteGO 2014年

4
@PeteGO是指Paul Dixon的答案。tldr; HAVING的评估要比WHERE评估更晚,更重要的是SELECT评估。
jairbow

38

参见下面的MySQL手册页:http : //dev.mysql.com/doc/refman/5.0/en/select.html

“可以使用AS alias_name为select_expr赋予别名。该别名用作表达式的列名,并且可以在GROUP BY,ORDER BY或HAVING子句中使用。”

(...)

不允许在WHERE子句中引用列别名,因为执行WHERE子句时可能尚未确定列值。请参见第B.5.4.4节“列别名的问题”。


另外,请注意(来自MySQL的人):SQL标准要求HAVING必须仅引用GROUP BY子句中的列或聚合函数中使用的列。但是,MySQL支持对此行为的扩展,并允许HAVING引用SELECT列表中的列以及外部子查询中的列。
Vincent Pazeller

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

像这样想,您的where子句首先求值,以确定需要返回哪些行(或联接的行)。一旦执行where子句,select子句便会为其运行。

为了更好地说明它,请想象一下:

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

没有第二部分,您将无法引用第一部分。在哪里总是先被评估,然后是select子句。


11

如果您尝试执行以下查询(查找所有带有至少一个附件的节点),则在其中使用SELECT语句创建数据库中实际上不存在的新字段,然后尝试使用该结果的别名会遇到相同的问题:

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

您将收到错误“ WHERE子句中的未知列'attachmentcount'”。

解决方案实际上非常简单-只需将别名替换为产生别名的语句即可,例如:

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
我正面临这个确切的问题,并且遇到了您的答案-谢谢!只是要注意,在大型数据库上,这是(可以理解的)有点慢,但是无论如何,我正在处理一个愚蠢的继承数据库设置。
Liam Newmarch

我相信您(在查询中还有一个额外功能,而(COUNT(*)这个功能在任何地方都无法关闭。
tftd 2012年

3
但是SELECT语句不是运行两次吗?
Matej

我到目前为止还没有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支持谓词推入内联视图,则后者应与前者相同。





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注入广泛开放的代码?
Nico Haase

1

可能有帮助。

您可以

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

有用。

但是请确定您要做什么!

  • 此处不使用索引
  • 将扫描FULL TABLE-您尚未指定LIMIT 1部分
  • 因此,-此查询将在大桌子上大放异彩。

但是,在某些情况下可能会有所帮助


0

虽然可以在查询中为表加别名(即“ SELECT u.username FROM users u;”),但您必须使用所引用列的实际名称。AS仅影响字段的返回方式。


我认为您可以在像MySql这样的RDBMS中使用别名。不过,您对Sql Server是正确的。
PeteGO 2014年

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

为什么要使用子查询?没有则简单得多。
PeteGO 2014年

0

刚遇到这个问题。

确保数据库中实体的名称中没有空格。

例如,“ user_name”而不是“ user_name”


-1

尝试使用IN条件或OR条件执行任务,并且此查询也适用于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注入。没有人应该使用此代码来解决给定的问题
Nico Haase
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.