甲骨文 SQL: 任意 + 为空

Oracle SQL: ANY + IS NULL

我需要用 NULL 检查几个字段。当然我可以用 OR.

SELECT * FROM table WHERE f1 IS NULL OR f2 IS NULL OR f3 IS NULL

但是 ANY 可以很好地处理逻辑运算。

是否可以在 Oracle SQL 中做类似的事情?

SELECT * FROM table WHERE ANY (f1, f2, f3) IS NULL

我使用 Oracle 12c。

在 Tim 的逆向分析器上,您可以使用 GREATEST 或 LEAST 来查找任何值为 NULL 的位置

select * from dual where greatest('a',2,3,null) is null;

Oracle 中使用表达式或函数的技巧:

如果这些都是数值,你可以只使用+:

with t(a, b, c) as (
  select 1, 2, 3 from dual union all 
  select null, 2, 3 from dual union all 
  select null, null, 3 from dual
)
select *
from t
where a + b + c is null;

它产生

A|B|C|
-|-|-|
 |2|3|
 | |3|

此外,可以使用可读性较差的 DECODE 函数,或 GREATEST as :

decode(null, a, 1, b, 1, c, 1, 0) = 1;

使用MINUS

您可以使用 (a, b, c) = ((a, b, c)) 检查值中的 none 是否为 NULL,在这种情况下谓词产生 NULL。不幸的是,由于 Oracle 不知道 BOOLEAN 类型,您不能 NULL 检查谓词本身(并且 LNNVL 似乎不适用于上述条件),但您可以使用 MINUS:

with t(a, b, c) as (
  select 1, 2, 3 from dual union all 
  select null, 2, 3 from dual union all 
  select null, null, 3 from dual
)
select *
from t
minus
select *
from t
where (a, b, c) = ((a, b, c)); -- None of the values is NULL

在很多情况下,这显然是一个缓慢的解决方案,所以不好。

标准 SQL:

值得一提的是,标准 SQL(例如由 PostgreSQL 而不是 Oracle 实现)支持行值表达式上的空谓词,如下所示:

not ((a, b, c) is not null)

"double negative" 是必要的,因为事实 table 表明 not x is nullx is not null 不是一回事 (source):

+-----------------------+-----------+---------------+---------------+-------------------+
| Expression            | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL |
+-----------------------+-----------+---------------+---------------+-------------------+
| degree 1: null        | true      | false         | false         |  true             |
| degree 1: not null    | false     | true          | true          |  false            |
| degree > 1: all null  | true      | false         | false         |  true             |
| degree > 1: some null | false     | false         | true          |  true             |
| degree > 1: none null | false     | true          | true          |  false            |
+-----------------------+-----------+---------------+---------------+-------------------+

使用行构造函数语法比较整行:

SELECT * 
FROM tab 
CROSS APPLY (SELECT CASE WHEN (f1,f2,f3)=((f1,f2,f3)) THEN 1 ELSE 0 END AS all_non_nulls  
             FROM dual) s
WHERE s.all_non_nulls = 0; -- 1 

db<>fiddle demo

(f1,f2,f3) -> 这是列列表