这个SQL怎么会出错?我没看到什么?

时间:2010-04-17 23:35:37

标签: sql mysql

任何人都可以发现我的错误,这应该是SQL中的合法查询不应该吗?

  

ON子句中的未知列u.usr_auto_key

这是数据库架构:

User: (usr_auto_key, name, etc...)
Setting: (set_auto_key, name etc..)
User_Setting: (usr_auto_key, set_auto_key, value)

这是查询...

        SELECT 
        `u`.`usr_auto_key` AS `u__usr_auto_key`, 
        `s`.`set_auto_key` AS `s__set_auto_key`, 
        `u2`.`usr_auto_key` AS `u2__usr_auto_key`, 
        `u2`.`set_auto_key` AS `u2__set_auto_key`, 
        `u2`.`value` AS `u2__value` 
        FROM `User` `u`, `Setting` `s` 
        LEFT JOIN `User_Setting` `u2` ON `u`.`usr_auto_key` = `u2`.`usr_auto_key` 
        WHERE (`s`.`sct_auto_key` = 1 AND `u`.`usr_auto_key` = 1 AND admin_property is null)

2 个答案:

答案 0 :(得分:4)

不要将SQL-89“逗号样式”连接语法与SQL-92 JOIN语法混合使用。这两种类型的连接操作的优先级存在微妙的问题。

在您的情况下,结果是它在LEFT JOIN表别名存在之前评估连接条件u。这就是为什么它不知道u.usr_auto_key是什么。

您可以对所有联接使用JOIN语法来解决此问题:

SELECT 
  `u`.`usr_auto_key` AS `u__usr_auto_key`, 
  `s`.`set_auto_key` AS `s__set_auto_key`, 
  `u2`.`usr_auto_key` AS `u2__usr_auto_key`, 
  `u2`.`set_auto_key` AS `u2__set_auto_key`, 
  `u2`.`value` AS `u2__value` 
FROM `User` `u` JOIN `Setting` `s`
LEFT JOIN `User_Setting` `u2` ON `u`.`usr_auto_key` = `u2`.`usr_auto_key` 
WHERE (`s`.`sct_auto_key` = 1 AND `u`.`usr_auto_key` = 1 AND admin_property is null)

我的查询中us之间没有看到任何加入条件,所以我假设您打算将其作为笛卡尔积?


有关连接的两种语法形式之间交互的更多详细信息,请参阅页面http://dev.mysql.com/doc/refman/5.0/en/join.html

上的加入MySQL 5.0.12中的处理更改部分

重新评论:正如我所说,它与运营商优先级有关。如果您有一个带有FROM A, B JOIN C的SQL查询,那么在它关注B JOIN C之前它会评估A - 包括分配表别名。因此,如果B JOIN C的加入条件使用A的表别名,则会收到错误,因为该别名尚不存在。

如果你反转它并运行B, A JOIN C,那么当它评估A JOIN C的连接条件时,A的别名是可用的并且它有效(至少在这种情况下)。

但这是一个脆弱的解决方案,因为您可能还需要一个无法通过重新排序AB来修复的查询。最好停止使用过时的连接语法和逗号。然后,任何连接表达式都可以访问所有表别名,并且在任何查询中都不会出现此问题。

答案 1 :(得分:1)

尝试在from子句中切换UserSettings

SELECT 
        `u`.`usr_auto_key` AS `u__usr_auto_key`, 
        `s`.`set_auto_key` AS `s__set_auto_key`, 
        `u2`.`usr_auto_key` AS `u2__usr_auto_key`, 
        `u2`.`set_auto_key` AS `u2__set_auto_key`, 
        `u2`.`value` AS `u2__value` 
        FROM `Setting` `s`, `Users` `u`
        LEFT JOIN `User_Setting` `u2` ON `u`.`usr_auto_key` = `u2`.`usr_auto_key` 
        WHERE (`s`.`sct_auto_key` = 1 AND `u`.`usr_auto_key` = 1 AND admin_property is null)