2013-05-06 73 views
3

当列不存在于profile表中时,为什么此查询会删除所有用户?Postgresql IN声明

初始查询

DELETE FROM users 
    WHERE user_id IN (
     SELECT user_id FROM profile 
     ) 
    AND user_id != 35 
    AND user_id != 6; 

更具体。

中的语句查询返回

SELECT user_id FROM profile; 

ERROR: column "user_id" does not exist 
LINE 1: SELECT user_id FROM profile; 

运行初始查询回报

DELETE 100

这是为什么发生?

它不应该在错误时停止执行或返回false或null吗?

运行PostgreSQL服务器9.0

+0

的[SQL Server 2008中的管理工作室不检查我的查询语法(HTTP可能重复: //www.stackoverflow.com/questions/4594733/sql-server-2008-management-studio-not-checking-the-syntax-of-my-query) – 2013-05-06 09:20:34

+9

这是正确的行为。子查询引用外部查询中的列是完全有效的。如果您想避免这种错误,请使用两个部分名称。 'DELETE FROM users WHERE user_id IN(SELECT p.user_id FROM profile p)''会给你一个无效的列名错误。 – 2013-05-06 09:22:06

+0

非常感谢@MartinSmith你是对的。 – 2013-05-06 09:29:55

回答

8

此行为是按照ANSI标准是正确的。

如果未限定的列名在内部作用域中未解析,则将考虑外部作用域。所以你有效地做了一个无意的相关子查询。

只要表profile包含至少一排然后

FROM users 
WHERE user_id IN (
     SELECT user_id FROM profile 
     ) 

最终会在users匹配的所有行(除了任何地方users.user_id IS NULL作为WHERE NULL IN (NULL)不计算为true)。为了避免这种可能的问题,您可以使用两个零件名称。

DELETE FROM users 
WHERE user_id IN (SELECT p.user_id 
        FROM profile p) 

会给错误

列p.user_id不存在:

+0

再次感谢您的详细描述。不胜感激! – 2013-05-07 10:29:33

+0

疯了,我是为了postgresql的“in”语句行为而使用googling,并且出现了。偶然发生这是我的问题。感谢这篇文章。 – 2014-02-14 17:15:40