【问题标题】:An error in a subquery returns all data for a query子查询中的错误返回查询的所有数据
【发布时间】:2020-10-26 10:25:37
【问题描述】:

我有以下数据结构:

用户:

  • 身份证
  • 姓名
  • status_id

帖子:

  • 身份证
  • 标题
  • user_id

以下查询返回所有博客行

select * from Post where user_id in (select user_id from User where status_id = 7);

虽然子查询

select user_id from User where status_id = 7

是错误的,如果单独执行,它会返回错误“错误:列“user_id”不存在”。是什么导致了这种行为?

【问题讨论】:

  • 今日提示:限定所有列!
  • 你实际上在做... in (select post.user_id from User......
  • 当然它会给你错误,因为user_id不在用户表中,列名是id检查它。这可能对您有用 select * from Post where user_id in (select id from User where status_id = 7);

标签: sql postgresql subquery where-clause correlated-subquery


【解决方案1】:

是什么导致了这种行为?

SQL 标准规定定义的子查询中标识符的可见性规则,如果子查询使用在子查询的任何表中可用的列,则该列引用直接“父”查询。

这是一个奇怪的规则,但它应该是这样工作的。

这种行为是强烈建议使用它们所属的表(别名)限定所有列引用的原因之一。

【讨论】:

  • 用别名举例可能会更好; SELECT a.column, b.another_column FROM a LEFT JOIN b ON....
  • 其实我的例子是 MySQL;所以可能不是 postgre 的正确语法?
【解决方案2】:

user 中没有 user_id 列,因此 Postgres 将其理解为对 postuser_id 的引用,它同时存在于外部范围和子查询 post 中:过滤变为 no- op,并返回post的所有行(只要user_id不是null)。

如果你要限定列名,你会得到你期望的错误:

select p.* 
from post p
where p.user_id in (select u.user_id from user u where u.status_id = 7);

不相关的旁注:我会用exists 代替查询:

select p.*
from post p
where exists (select 1 from user u where u.status_id = 7 and u.id = p.user_id)

此查询将利用user(id, status_id) 上的索引。

【讨论】:

    【解决方案3】:

    当然它会给你错误,因为 user_id 不在用户表中,列是 id 检查它。 试试这个

     select * from Post where user_id in (select id from User where status_id = 7); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-15
      • 2012-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-29
      • 1970-01-01
      相关资源
      最近更新 更多