是否有一个概念(带有实现 - 在Oracle SQL中为初学者)表现得像一个"通用"匹配器?
我的意思是;我知道 NULL 不等于任何东西——包括 NULL。 这就是为什么你必须小心在SQL表达式中使用"IS NULL"而不是"=NULL"。
我也知道使用 NVL(在 Oracle 中)函数来检测 NULL 并将其替换为输出中的某些内容很有用。
但是:使用 NVL 替换 NULL 的内容必须与基础列的数据类型匹配;否则,您将(正确地)收到错误。
举个例子:
我有一个表,其中包含类型为 VARCHAR2 的 NULLABLE 列"name";它包含一个 NULL 行。
我可以取出 NULL 并将其替换为如下所示的 NVL:
SELECT NVL(name, 'NullyMcNullFace’) from my_table;
伟大。
但是,如果该列碰巧是一个数字(例如"年龄"),那么我必须更改我的NVL:
SELECT NVL(age, 32) from my_table;
也很棒。
现在,如果该列恰好是DATE(例如"某个日期"),那么我必须再次更改我的NVL:
SELECT NVL(somedate, sysdate) from my_table;
我在这里得到的是:为了处理NULL,你必须用特定的东西替换;并且这个特定的东西必须"适合"数据类型。
那么这里是否有像"ANY"这样的结构/概念(因为没有更好的词)。 其中"ANY"适合任何数据类型的列(如NULL),但(与NULL不同,与所有其他特定值不同)将与任何内容(包括NULL - ?
这样我就可以做到:
SELECT NVL(whatever_column, ANY) from my_table;
我认为答案可能是否定的;而且可能是"走开,空值已经够糟糕的了——别介意你半想的这个怪物"。
不,SQL 中没有等于一切的"通用接受器"值。
您可以做的是将NVL提高到您的比较中。就像你尝试做一个联接一样:
SELECT ...
FROM my_table AS m
JOIN other_table AS o ON o.name = NVL(m.name, o.name)
因此,如果m.name
为 NULL,则连接会将o.name
与o.name
进行比较,这当然总是正确的。
对于 NULL 的其他用法,您可能必须使用适合这种情况的另一种技术。
在对比尔·卡文的回答的评论中解决这个问题:
如果 NEW 和 OLD 值不同,我想输出 1,如果它们相同,我想输出 0。但是(出于我的目的)我也想为两个 NULL 返回 0。
select
Case When (:New = :Old) or
(:New is NULL and :Old is NULL) then 0
Else
1
End
from dual
在 WHERE 子句中,你可以放置这样的条件,
WHERE column1 LIKE NVL(any_column_or_param, '%')
也许DECODE()
适合你在这里的目的?
WITH t1 AS (SELECT 1 ID, NULL val FROM dual UNION ALL
SELECT 2 ID, NULL val FROM dual UNION ALL
SELECT 3 ID, 1 val FROM dual UNION ALL
SELECT 4 ID, 2 val FROM dual UNION ALL
SELECT 5 ID, 5 val FROM dual),
t2 AS (SELECT 1 ID, NULL val FROM dual UNION ALL
SELECT 2 ID, 3 val FROM dual UNION ALL
SELECT 3 ID, 1 val FROM dual UNION ALL
SELECT 4 ID, 4 val FROM dual UNION ALL
SELECT 6 ID, 5 val FROM dual)
SELECT t1.id t1_id,
t1.val t1_val,
t2.id t2_id,
t2.val t2_val,
DECODE(t1.val, t2.val, 0, 1) different_vals
FROM t1
FULL OUTER JOIN t2 ON t1.id = t2.id
ORDER BY COALESCE(t1.id, t2.id);
T1_ID T1_VAL T2_ID T2_VAL DIFFERENT_VALS
---------- ---------- ---------- ---------- --------------
1 1 0
2 2 3 1
3 1 3 1 0
4 2 4 4 1
5 5 1
6 5 1