Where 子句中的未知列
Posted
技术标签:
【中文标题】Where 子句中的未知列【英文标题】:Unknown Column In Where Clause 【发布时间】:2008-09-30 15:37:17 【问题描述】:我有一个简单的查询:
SELECT u_name AS user_name FROM users WHERE user_name = "john";
我收到Unknown Column 'user_name' in where clause
。即使在select 'u_name as user_name'
之后,我也可以在声明的其他部分不提及'user_name'
吗?
【问题讨论】:
【参考方案1】:SQL 是从右到左向后计算的。因此 where 子句在 select 子句之前被解析和评估。因此,u_name 到 user_name 的别名尚未发生。
【讨论】:
比起“向后”,我认为说“由内而外”更有意义 在一个复杂的多阶段过程中将整个语句作为一个整体进行解析、转换和优化更有意义。 “SQL 是从右到左向后评估的”是错误的 不完整的答案,因为用户询问是否可以在语句中使用'user_name',它可以在例如之后'拥有'【参考方案2】:怎么样:
SELECT u_name AS user_name FROM users HAVING user_name = "john";
【讨论】:
在这种情况下为什么要使用HAVING
而不是WHERE
?
@PeteGO 参考 Paul Dixon 的回答。 tldr; HAVING 的评估晚于 WHERE,更重要的是 SELECT。【参考方案3】:
请参阅以下 mysql 手册页:http://dev.mysql.com/doc/refman/5.0/en/select.html
"一个 select_expr 可以被赋予一个别名 使用 AS 别名。使用了别名 作为表达式的列名和 可用于 GROUP BY、ORDER BY 或 HAVING 子句。”
(...)
不允许在 WHERE 子句中引用列别名, 因为在 WHERE 时可能尚未确定列值 子句被执行。请参阅第 B.5.4.4 节,“列问题 别名”。
【讨论】:
另外,请注意(来自 MySQL man):SQL 标准要求 HAVING 必须仅引用 GROUP BY 子句中的列或聚合函数中使用的列。但是,MySQL 支持对此行为的扩展,并允许 HAVING 引用 SELECT 列表中的列和外部子查询中的列。【参考方案4】: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";
没有后半部分就不能引用前半部分。 where 总是首先被评估,然后是 select 子句。
【讨论】:
【参考方案5】:如果您尝试执行如下查询(查找所有具有至少一个附件的节点),其中您使用 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 不应该在未知别名处出错。
【讨论】:
我遇到了这个确切的问题,并遇到了您的答案 - 谢谢!请注意,在大型数据库上它(可以理解)有点慢,但无论如何我正在处理一个愚蠢的继承数据库设置。 我相信您的查询中有一个额外的(
在(COUNT(*)
之前,它不会在任何地方关闭。
但是SELECT语句不是运行两次吗?
我目前还不是 mysql 专家,但这似乎非常不规范。我体验过嵌套选择会使查询慢得多。【参考方案6】:
WHERE
子句不欢迎您定义的alias
,您必须为此使用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 支持将谓词推入内联视图,则后者应该与前者相同。
【讨论】:
【参考方案8】:更正:
SELECT u_name AS user_name FROM users WHERE u_name = 'john';
【讨论】:
【参考方案9】:不,您需要使用正确的名称选择它。如果你给了你从别名中选择的表,你可以使用它。
【讨论】:
【参考方案10】:不,你不能。 user_name 直到返回时间才存在。
【讨论】:
【参考方案11】:SELECT user_name
FROM
(
SELECT name AS user_name
FROM users
) AS test
WHERE user_name = "john"
【讨论】:
为什么要使用子查询?没有就简单多了。【参考方案12】:WHERE
子句中的未知列由第 1 行和第 2 行引起并由第 3 行解决:
$sql = "SELECT * FROM users WHERE username =".$userName;
$sql = "SELECT * FROM users WHERE username =".$userName."";
$sql = "SELECT * FROM users WHERE username ='".$userName."'";
【讨论】:
你改变了什么,为什么?此外,您为什么发布对 SQL 注入广泛开放的代码?【参考方案13】:可能会有帮助。
你可以
SET @somevar := '';
SELECT @somevar AS user_name FROM users WHERE (@somevar := `u_name`) = "john";
有效。
但要确定你做什么!
此处不使用索引 将扫描 FULL TABLE - 您尚未指定 LIMIT 1 部分 所以, - 这个查询将在大表上 SLLLOOOOOOW。但是,在某些情况下可能会有所帮助
【讨论】:
【参考方案14】:虽然您可以在查询中为表设置别名(例如,“SELECT u.username FROM users u;”),但您必须使用所引用列的实际名称。 AS 只影响字段的返回方式。
【讨论】:
我认为您可以在某些 RDBMS 中使用别名,例如 MySql。不过,您对 Sql Server 是正确的。【参考方案15】:刚刚遇到这个问题。
确保数据库中实体名称中没有空格。
例如'user_name' 而不是 'user_name'
【讨论】:
【参考方案16】:对我来说,问题的根源是我复制的一个数字,以便在 WHERE 子句中使用。该数字具有“隐形”符号,至少对于 MySQL Workbench 而言。我将数字放在 Chrome 控制台中,它清晰可见。
【讨论】:
【参考方案17】:我遇到了同样的问题,我发现这很有用。
mysql_query("SELECT * FROM `users` WHERE `user_name`='$user'");
记得将 $user 放在 ' ' 单引号中。
【讨论】:
该代码对 SQL 注入广泛开放。没有人应该使用此代码来解决给定的问题以上是关于Where 子句中的未知列的主要内容,如果未能解决你的问题,请参考以下文章
错误代码:1054。“where 子句”中的未知列“sdate”