Postgres 9.5 atau lebih baru
Atau gunakan array_position()
. Pada dasarnya:
SELECT array_position(arr, NULL) IS NOT NULL AS array_has_null
Lihat demo di bawah.
Postgres 9.3 atau lebih baru
Anda dapat menguji dengan fungsi bawaan array_remove()
atau array_replace()
.
Postgres 9.1 atau versi apa pun
Jika Anda tahu elemen tunggal yang tidak akan pernah ada dalam array Anda, Anda dapat menggunakan cepat ini ekspresi. Katakanlah, Anda memiliki larik bilangan positif, dan -1
tidak pernah bisa di dalamnya:
-1 = ANY(arr) IS NULL
Jawaban terkait dengan penjelasan rinci:
- Apakah array semua NULL di PostgreSQL
Jika Anda tidak bisa benar-benar yakin , Anda bisa kembali ke salah satu yang mahal tapi aman metode dengan unnest()
. Seperti:
(SELECT bool_or(x IS NULL) FROM unnest(arr) x)
atau:
EXISTS (SELECT 1 FROM unnest(arr) x WHERE x IS NULL)
Tetapi Anda dapat memiliki cepat dan aman dengan CASE
ekspresi. Gunakan nomor yang tidak mungkin dan kembali ke metode aman jika memang ada. Anda mungkin ingin menangani kasus arr IS NULL
terpisah. Lihat demo di bawah.
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);
Hasil:
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
Perhatikan bahwa array_remove()
dan array_position()
tidak diperbolehkan untuk array multidimensi . Semua ekspresi di sebelah kanan t_93a
hanya bekerja untuk array 1-dimensi.
db<>main biola di sini - Postgres 13, dengan lebih banyak tes
sqlfiddle lama
Penyiapan tolok ukur
Waktu yang ditambahkan berasal dari uji benchmark dengan 200 ribu baris di Postgres 9.5 . Ini adalah pengaturan saya:
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;
Pembungkus fungsi
Untuk penggunaan berulang , saya akan membuat fungsi di Postgres 9.5 seperti ini:
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
hanya untuk Postgres 9.6 atau lebih baru.
Menggunakan jenis input polimorfik ini berfungsi untuk apa saja tipe array, bukan hanya int[]
.
Jadikan IMMUTABLE
untuk memungkinkan pengoptimalan kinerja dan ekspresi indeks.
- Apakah PostgreSQL mendukung kumpulan "aksen tidak sensitif"?
Tapi jangan dibuat STRICT
, yang akan menonaktifkan "fungsi inlining" dan merusak kinerja karena array_position()
bukan STRICT
diri. Lihat:
- Fungsi dijalankan lebih cepat tanpa pengubah STRICT?
Jika Anda perlu menangkap kasus 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';
Untuk Postgres 9.1 gunakan t_91
ekspresi dari atas. Sisanya berlaku tidak berubah.
Berhubungan erat:
- Bagaimana cara menentukan apakah NULL terkandung dalam array di Postgres?