根据this question,在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应用于多个列。对此有更好的选择吗?
答案 0 :(得分:5)
好吧,我不确定这是否更好,但使用LNNVL
这个函数可能会稍微简洁一点(你只能在{{1}中使用如果给定表达式为WHERE
或UNKNOWN(TRUE
),则返回FALSE
。例如......
NULL
...将返回除X = 1和Y = 2之外的所有行。
答案 1 :(得分:2)
作为替代方案,您可以使用NVL
函数和指定的文字,如果值为null,将返回该文字:
-- 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
答案 2 :(得分:1)
使用LNNVL
功能,当col1
和col2
(答案中的x
和y
)都为空时,您仍会遇到问题。使用nvl
它可以工作,但效率很低(优化器不理解),你必须找到一个不能出现在数据中的值(优化器应该知道它不能)。
对于字符串,您可以选择一个字符数多于列的最大值但值很脏的值。
真正有效的方法是使用(未记录的)函数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')