Postgres 9.5 lub nowszy
Lub użyj array_position()
. Zasadniczo:
SELECT array_position(arr, NULL) IS NOT NULL AS array_has_null
Zobacz demo poniżej.
Postgres 9.3 lub nowszy
Możesz testować za pomocą wbudowanych funkcji array_remove()
lub array_replace()
.
Postgres 9.1 lub dowolna wersja
Jeśli wiesz pojedynczy element, który nigdy nie może istnieć w twoich tablicach, możesz użyć tego szybkiego wyrażenie. Powiedzmy, że masz tablicę liczb dodatnich i -1
nigdy w nim nie może być:
-1 = ANY(arr) IS NULL
Powiązana odpowiedź ze szczegółowym wyjaśnieniem:
- Czy tablica zawiera wszystkie wartości NULL w PostgreSQL
Jeśli nie masz całkowitej pewności , możesz wrócić do jednego z drogich, ale bezpiecznych metody z unnest()
. Na przykład:
(SELECT bool_or(x IS NULL) FROM unnest(arr) x)
lub:
EXISTS (SELECT 1 FROM unnest(arr) x WHERE x IS NULL)
Ale możesz mieć szybko i bezpiecznie z CASE
wyrażenie. Użyj mało prawdopodobnej liczby i wróć do bezpiecznej metody, jeśli powinna istnieć. Możesz zająć się sprawą arr IS NULL
osobno. Zobacz demo poniżej.
Demo
SELECT num, arr, expect
, -1 = ANY(arr) IS NULL AS t_1 -- 50 ms
, (SELECT bool_or(x IS NULL) FROM unnest(arr) x) AS t_2 -- 754 ms
, EXISTS (SELECT 1 FROM unnest(arr) x WHERE x IS NULL) AS t_3 -- 521 ms
, CASE -1 = ANY(arr)
WHEN FALSE THEN FALSE
WHEN TRUE THEN EXISTS (SELECT 1 FROM unnest(arr) x WHERE x IS NULL)
ELSE NULLIF(arr IS NOT NULL, FALSE) -- catch arr IS NULL -- 55 ms
-- ELSE TRUE -- simpler for columns defined NOT NULL -- 51 ms
END AS t_91
, array_replace(arr, NULL, 0) <> arr AS t_93a -- 99 ms
, array_remove(arr, NULL) <> arr AS t_93b -- 96 ms
, cardinality(array_remove(arr, NULL)) <> cardinality(arr) AS t_94 -- 81 ms
, COALESCE(array_position(arr, NULL::int), 0) > 0 AS t_95a -- 49 ms
, array_position(arr, NULL) IS NOT NULL AS t_95b -- 45 ms
, CASE WHEN arr IS NOT NULL
THEN array_position(arr, NULL) IS NOT NULL END AS t_95c -- 48 ms
FROM (
VALUES (1, '{1,2,NULL}'::int[], true) -- extended test case
, (2, '{-1,NULL,2}' , true)
, (3, '{NULL}' , true)
, (4, '{1,2,3}' , false)
, (5, '{-1,2,3}' , false)
, (6, NULL , null)
) t(num, arr, expect);
Wynik:
num | arr | expect | t_1 | t_2 | t_3 | t_91 | t_93a | t_93b | t_94 | t_95a | t_95b | t_95c -----+-------------+--------+--------+------+-----+------+-------+-------+------+-------+-------+------- 1 | {1,2,NULL} | t | t | t | t | t | t | t | t | t | t | t 2 | {-1,NULL,2} | t | f --!! | t | t | t | t | t | t | t | t | t 3 | {NULL} | t | t | t | t | t | t | t | t | t | t | t 4 | {1,2,3} | f | f | f | f | f | f | f | f | f | f | f 5 | {-1,2,3} | f | f | f | f | f | f | f | f | f | f | f 6 | NULL | NULL | t --!! | NULL | f | NULL | NULL | NULL | NULL | f | f | NULL
Zauważ, że array_remove()
i array_position()
nie są dozwolone dla tablic wielowymiarowych . Wszystkie wyrażenia na prawo od t_93a
działa tylko dla tablic jednowymiarowych.
db<>graj tutaj - Postgres 13, więcej testów
Stary sqlfiddle
Konfiguracja testu porównawczego
Dodane czasy pochodzą z testu porównawczego z 200 tys. wierszy w Postgres 9.5 . Oto moja konfiguracja:
CREATE TABLE t AS
SELECT row_number() OVER() AS num
, array_agg(elem) AS arr
, bool_or(elem IS NULL) AS expected
FROM (
SELECT CASE WHEN random() > .95 THEN NULL ELSE g END AS elem -- 5% NULL VALUES
, count(*) FILTER (WHERE random() > .8)
OVER (ORDER BY g) AS grp -- avg 5 element per array
FROM generate_series (1, 1000000) g -- increase for big test case
) sub
GROUP BY grp;
Opakowanie funkcji
Do wielokrotnego użytku , utworzyłbym funkcję w Postgresie 9,5 tak:
CREATE OR REPLACE FUNCTION f_array_has_null (anyarray)
RETURNS bool
LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'SELECT array_position($1, NULL) IS NOT NULL';
PARALLEL SAFE
tylko dla Postgresa 9.6 lub nowszego.
Używając polimorficznego typu danych wejściowych, działa to dla dowolnych typ tablicy, nie tylko int[]
.
Zrób to IMMUTABLE
aby umożliwić optymalizację wydajności i wyrażenia indeksujące.
- Czy PostgreSQL obsługuje sortowanie „niewrażliwe na akcenty”?
Ale nie rób tego STRICT
, co wyłączyłoby „umieszczanie funkcji” i pogorszyło wydajność, ponieważ array_position()
nie jest STRICT
samo. Zobacz:
- Funkcja działa szybciej bez modyfikatora STRICT?
Jeśli chcesz złapać przypadek arr IS NULL
:
CREATE OR REPLACE FUNCTION f_array_has_null (anyarray)
RETURNS bool
LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'SELECT CASE WHEN $1 IS NOT NULL
THEN array_position($1, NULL) IS NOT NULL END';
Dla Postgresa 9.1 użyj t_91
wyrażenie z góry. Reszta obowiązuje bez zmian.
Ściśle powiązane:
- Jak ustalić, czy w Postgresie znajduje się tablica NULL?