Oracle 中 IN 的行为

Behavior of IN in Oracle

我编写了一个子查询来连接两个 table 并获取数据,其中一个 ID 列对于两个连接是通用的。但是列名称不同,如下所示。

我写的这个:

SELECT parent_id ,name   
FROM parent_table 
WHERE parent_id IN (SELECT parent_id 
                    FROM child_table 
                    WHERE country IN ('US'));

它将父 table 中的所有行作为 子查询 SELECT parent_id FROM child_table WHERE country IN ('US') 似乎不正确。 table 中没有 parent_id 列。

以下查询正确的是:

SELECT parent_id ,name   
FROM parent_table 
WHERE parent_id IN (SELECT child_id 
                    FROM child_table 
                    WHERE country IN ('US'));

现在我的问题是:为什么第一个查询没有给出任何错误,因为子查询不正确?

隔离执行的子查询将return ORA-00904.

子查询可能包含对外部查询 table 的引用。由于您没有限定列,并且 child_table 没有 parent_id 列,因此您的查询

SELECT parent_id ,name   
FROM parent_table WHERE parent_id IN ( SELECT parent_id FROM child_table WHERE country IN ('US'));

将被评估为

SELECT parent_id ,name   
FROM parent_table WHERE parent_id IN ( SELECT parent_table.parent_id FROM child_table WHERE country IN ('US'));

这将 return 所有 parent_table 行,只要 child_table 至少有一个 'US' 行。

始终限定列(当涉及多个 table 时)是一种很好的编程习惯。还可以使用 table 别名来节省一些输入。

SELECT pt.parent_id, pt.name   
FROM parent_table pt WHERE pt.parent_id IN ( SELECT ct.child_id FROM child_table ct WHERE ct.country IN ('US'));

Oracle 正在使用来自外部查询的 parent_id 列。

如果您用它们引用的表限定列,那么 Oracle 正在做:

SELECT parent_table.parent_id,
       parent_table.name   
FROM   parent_table
WHERE  parent_table.parent_id IN (
  SELECT parent_table.parent_id
--       ^^^^^^
  FROM   child_table
  WHERE  child_table.country IN ('US')
);

这将 return 所有行并且不会引发异常。

但你期待的是:

SELECT parent_table.parent_id,
       parent_table.name   
FROM   parent_table
WHERE  parent_table.parent_id IN (
  SELECT child_table.parent_id
--       ^^^^^
  FROM   child_table
  WHERE  child_table.country IN ('US')
);

这会引发异常,因为 child_table 中没有 parent_id 列。