最简单的SQL表达式,用于检查两列是否具有相同的NULL值

时间:2015-12-10 20:18:49

标签: sql oracle oracle11g null

我试图弄清楚最简单的通用 SQL表达式,它可以检查两列ab是否相同。换句话说,在以下情况下计算结果为true的表达式:

  1. aNULLbNULL;或
  2. a不是NULLb不是NULLa = b
  3. 假设列ab具有完全相同的数据类型。

    我在下面的例子中使用的最明显的解决方案非常令人费解,特别是因为我需要在15列表中重复这个条款15x:

    SELECT * FROM (
    
        SELECT 'x' a, 'x' b FROM dual
            UNION ALL
        SELECT 'x' a, NULL b FROM dual
            UNION ALL
        SELECT NULL a, 'x' b FROM dual
            UNION ALL
        SELECT NULL a, NULL b FROM dual
            UNION ALL
        SELECT 'x' a, 'y' b FROM dual
            UNION ALL
        SELECT 'x' a, NULL b FROM dual
            UNION ALL
        SELECT NULL a, 'y' b FROM dual
            UNION ALL
        SELECT NULL a, NULL b FROM dual
    
    )
    
    WHERE (a IS NULL AND b IS NULL) OR
          (a IS NOT NULL AND b IS NOT NULL AND a = b)
    /
    

    预期结果是:

    +--------+--------+
    |   a    |   b    |
    +--------+--------+
    | x      | x      |
    | (null) | (null) |
    | (null) | (null) |
    +--------+--------+
    

    tl; dr - 我可以简化我的WHERE条款,使其更紧凑,同时保持逻辑正确吗?

    P.S。:我无法对任何SQL纯粹主义者坚持认为" NULL不是一个值"。对于我的实用目的,如果a包含NULLb没有,则a 与{{不同 1}}。它不是"未知"他们是否不同所以,请提前告知那条小巷没有争论!

    P.P.S。:我的SQL风格是Oracle 11g。

    P.P.P.S。:有人认为这个问题与" Is there better Oracle operator to do null-safe equality check?"但粗略检查一下这个问题将会显示答案没有比这个帖子上发布的答案更有帮助,并且不满足我特定的,明确规定的标准。仅仅因为它们相似并不能使它们重复。我永远不明白为什么SO上的人如此努力地迫使我的问题X成为别人的问题Y.

4 个答案:

答案 0 :(得分:2)

您可以将其简化为:

WHERE (a IS NULL AND b IS NULL) OR
      (a = b)

不需要IS NOT NULL

如果您有一个“安全”值(即从未使用过的值),您可以这样做:

WHERE COALESCE(a, ' ') = COALESCE(b, ' ')

这假定' '不是有效值。

答案 1 :(得分:1)

我发现Ask Tom文章"Safely Comparing NULL Columns As Equal"最有帮助。在Oracle中,您可以使用DECODE函数执行此操作:

 WHERE 1 = DECODE(a, b, 1, 0)

这是迄今为止我见过的最紧凑的解决方案。

答案 2 :(得分:0)

简单不一定是高效的。

考虑这种可能性。

WHERE X || 'x' = Y || 'x'

如果您想真正推动信封,请使用 SYS_OP_MAP_NONNULL

答案 3 :(得分:-1)

SELECT * FROM (

SELECT 'x' a, 'x' b FROM dual
    UNION ALL
SELECT 'x' a, NULL b FROM dual
    UNION ALL
SELECT NULL a, 'x' b FROM dual
    UNION ALL
SELECT NULL a, NULL b FROM dual
    UNION ALL
SELECT 'x' a, 'y' b FROM dual
    UNION ALL
SELECT 'x' a, NULL b FROM dual
    UNION ALL
SELECT NULL a, 'y' b FROM dual
    UNION ALL
SELECT NULL a, NULL b FROM dual

)

WHERE NVL(a,'1')=NVL(b,'1')