Oracle SQL: ЛЮБОЙ + ЕСТЬ НУЛЬ - PullRequest
3 голосов
/ 30 апреля 2020

Мне нужно проверить несколько полей с NULL. Конечно, я могу сделать это с OR.

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

Но есть ANY, который отлично работает с логическими операциями.

Возможно ли сделать что-то подобное в Oracle s SQL?

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

Я использую Oracle 12 c.

Ответы [ 3 ]

3 голосов
/ 30 апреля 2020

Трюк в Oracle с использованием выражений или функций:

Если это все числовые значения c, вы можете просто использовать +:

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, как Гари уже показал :

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

Использование MINUS

Вы можете использовать (a, b, c) = ((a, b, c)), чтобы проверить, является ли ни одно из значений 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)

"Двойной отрицательный" необходим, поскольку таблица истинности показывает, что not x is null и x is not null это не одно и то же ( источник ):

+-----------------------+-----------+---------------+---------------+-------------------+
| 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            |
+-----------------------+-----------+---------------+---------------+-------------------+
3 голосов
/ 30 апреля 2020

В обратном порядке к anser Тима вы можете использовать GREATEST или LEAST, чтобы посмотреть, где любое значение равно NULL

select * from dual where greatest('a',2,3,null) is null;
1 голос
/ 30 апреля 2020

Сравнение целых строк с синтаксисом конструктора строк:

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) -> здесь идет список столбцов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...