2012-11-16 21 views
2

this question,順便去執行Oracle中的平等檢查,我希望NULL被視爲相等空是一樣的東西有沒有更好的Oracle操作符來進行空值平等檢查?

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)) 

這可真讓我的代碼髒,尤其是當我有很多的像這樣以及哪裏適用於多列。有更好的選擇嗎?

+0

另外相關http://stackoverflow.com/questions/636886/sql-not-equals-null –

+0

太糟糕了,Oracle不支持標準'IS NOT DISTINCT FROM'運算符。 –

回答

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 
+3

只有找到源數據中未使用的值(本例中爲-1),此模式纔有效。如果-1是源數據的一部分,則比較可能返回錯誤的結果。 – Codo

+0

@Codo絕對正確。 –

5

嗯,我不知道這是更好,但它可能會稍微更簡潔使用LNNVL ,一個函數(只能在WHERE子句中使用),如果給定表達式爲FALSE或UNKNOWN(NULL),則返回TRUE。例如...

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

+0

upvote for lnnvl –

1

隨着LNNVL功能,你還有一個問題,當col1col2x和答案中的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')

相關問題