3

根据这个问题,在 Oracle 中执行相等检查的方式,我希望 null 被视为等于 null 类似于

SELECT  COUNT(1)
  FROM    TableA
WHERE 
  wrap_up_cd = val
  AND ((brn_brand_id = filter) OR (brn_brand_id IS NULL AND filter IS NULL))

这真的会让我的代码变脏,特别是如果我有很多这样的 where 并且 where 应用于多个列。有没有更好的选择呢?

4

3 回答 3

5

好吧,我不确定这是否更好LNNVL,但使用函数(只能在WHERE子句中使用)可能会更简洁一些,TRUE如果给定表达式是FALSE或 UNKNOWN ( NULL) 则返回。例如...

WITH T AS
(
    SELECT    1 AS X,    1 AS Y FROM DUAL UNION ALL
    SELECT    1 AS X,    2 AS Y FROM DUAL UNION ALL
    SELECT    1 AS X, NULL AS Y FROM DUAL UNION ALL
    SELECT NULL AS X,    1 AS Y FROM DUAL
)
SELECT
    *
FROM
    T
WHERE
    LNNVL(X <> Y);

...将返回除 X = 1 和 Y = 2 的行之外的所有行。

于 2012-11-16T12:44:23.080 回答
2

使用该函数,当和(和在答案中) 都为空LNNVL时,您仍然会遇到问题。它可以工作,但效率低下(优化器不理解),您必须找到一个不能出现在数据中的值(优化器应该知道它不能)。 对于字符串,您可以选择一个字符数超过列的最大值但它很脏的值。col1col2xynvl

真正有效的方法是使用(未记录的)函数SYS_OP_MAP_NONNULL()

像这样:

where SYS_OP_MAP_NONNULL(col1) <> SYS_OP_MAP_NONNULL(col2)

SYS_OP_MAP_NONNULL(a)相当于nvl(a,'some internal value that cannot appear in the data but that is not null')

于 2015-03-08T16:25:03.577 回答
2

作为替代方案,您可以使用NVL函数和指定文字,如果值为空,则将返回:

-- both are not nulls
SQL> with t1(col1, col2) as(
  2    select 123, 123 from dual
  3  )
  4  select 1 res
  5    from t1
  6  where nvl(col1, -1) = nvl(col2, -1)
  7  ;

       RES
----------
         1

-- one of the values is null
SQL> with t1(col1, col2) as(
  2    select null, 123 from dual
  3  )
  4  select 1 res
  5    from t1
  6  where nvl(col1, -1) = nvl(col2, -1)
  7  ;

  no rows selected

 -- both values are nulls
 SQL> with t1(col1, col2) as(
  2    select null, null from dual
  3  )
  4  select 1 res
  5    from t1
  6  where nvl(col1, -1) = nvl(col2, -1)
  7  ;

       RES
----------
         1

正如@Codo 在评论中指出的那样,当然,上述方法需要选择一个永远不会有的文字比较列。如果比较列是数字数据类型(例如)并且能够接受任何值,那么选择 -1 当然不是一个选项。为了消除这种限制,我们可以使用decode函数(用于数字或字符数据类型):

 with t1(col1, col2) as(
  2    select null, null from dual
  3  )
  4  select 1 res
  5    from t1
  6  where decode(col1, col2, 'same', 'different') = 'same'
  7  ;

       RES
----------
         1
于 2012-11-16T07:23:25.190 回答