为什么我不能在连接中使用空值?

Mar*_*ner 13 null oracle join

我已经通过使用解决了查询问题 ... row_number() over (partition by... 这是关于为什么我们不能在连接中使用具有空值的列的更一般的问题。为什么为了连接而 null 不能等于 null?

a_h*_*ame 31

为什么为了连接而 null 不能等于 null?

只需告诉 Oracle 这样做:

select *
from one t1 
  join two t2 on coalesce(t1.id, -1) = coalesce(t2.id, -1);
Run Code Online (Sandbox Code Playgroud)

(请注意,在标准 SQL 中,您可以使用t1.id is not distinct from t2.id获得空安全的相等运算符,但 Oracle 不支持)

但这只有在替换值(上例中的 -1)实际上没有出现在表中时才有效。为数字找到这样一个“神奇”的值可能是可能的,但对于字符值将非常困难(特别是因为 Oracle 也将空字符串视为null

另外:不会id使用列上的索引(尽管您可以使用coalesce()表达式定义基于函数的索引)。

另一个适用于所有类型的选项,没有魔法值:

              on t1.id = t2.id or (t1.id is null and t2.id is null)
Run Code Online (Sandbox Code Playgroud)

但真正的问题是:这有意义吗?

考虑以下示例数据:

表一

select *
from one t1 
  join two t2 on coalesce(t1.id, -1) = coalesce(t2.id, -1);
Run Code Online (Sandbox Code Playgroud)

表二

              on t1.id = t2.id or (t1.id is null and t2.id is null)
Run Code Online (Sandbox Code Playgroud)

连接中应该选择哪个空值组合?我上面的例子将导致类似于所有空值的交叉连接。

id
----
1
2
(null)
(null)
Run Code Online (Sandbox Code Playgroud)


And*_*y M 6

或者,您可以使用INTERSECT相等运算符使两个空值相互匹配:

SELECT
  *
FROM
  t1
  INNER JOIN t2
    ON EXISTS (SELECT t1.ID FROM DUAL INTERSECT SELECT t2.ID FROM DUAL)
;
Run Code Online (Sandbox Code Playgroud)

有关说明,请参阅此 DBFiddle 演示

当然,这看起来是挺满嘴的,虽然实际上比BriteSponge 的建议长不了多少。但是,如果您原谅双关语,它肯定与前面在注释标准方式中提到的简洁性不匹配,即IS NOT DISTINCT FROMOracle 尚不支持的运算符。