甲骨文 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 null
和 x 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
(f1,f2,f3)
-> 这是列列表
我需要用 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 null
和 x 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
(f1,f2,f3)
-> 这是列列表