Postgres 9.5 trở lên
Hoặc sử dụng array_position()
. Về cơ bản:
SELECT array_position(arr, NULL) IS NOT NULL AS array_has_null
Xem bản trình diễn bên dưới.
Postgres 9.3 trở lên
Bạn có thể kiểm tra với các hàm tích hợp sẵn array_remove()
hoặc array_replace()
.
Postgres 9.1 hoặc bất kỳ phiên bản nào
Nếu bạn biết một phần tử duy nhất không bao giờ có thể tồn tại trong các mảng của bạn, bạn có thể sử dụng tính năng này nhanh biểu hiện. Giả sử, bạn có một mảng các số dương và -1
không bao giờ có thể ở trong đó:
-1 = ANY(arr) IS NULL
Câu trả lời liên quan với giải thích chi tiết:
- Là mảng có tất cả các NULL trong PostgreSQL
Nếu bạn không thể chắc chắn hoàn toàn , bạn có thể rơi trở lại một trong những đắt tiền nhưng an toàn phương thức với unnest()
. Như:
(SELECT bool_or(x IS NULL) FROM unnest(arr) x)
hoặc:
EXISTS (SELECT 1 FROM unnest(arr) x WHERE x IS NULL)
Nhưng bạn có thể có nhanh chóng và an toàn với CASE
biểu hiện. Sử dụng một số không chắc chắn và quay trở lại phương pháp an toàn nếu nó nên tồn tại. Bạn có thể muốn xử lý trường hợp arr IS NULL
riêng biệt. Xem bản trình diễn bên dưới.
Bản trình diễn
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);
Kết quả:
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
Lưu ý rằng array_remove()
và array_position()
không được phép đối với mảng nhiều chiều . Tất cả các biểu thức ở bên phải của t_93a
chỉ hoạt động cho mảng 1 chiều.
db <> fiddle here - Postgres 13, với nhiều thử nghiệm hơn
Old sqlfiddle
Thiết lập điểm chuẩn
Thời gian được thêm vào là từ kiểm tra điểm chuẩn với 200 nghìn hàng trong Postgres 9.5 . Đây là thiết lập của tôi:
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;
Trình bao bọc hàm
Để sử dụng nhiều lần , Tôi sẽ tạo một hàm trong Postgres 9.5 như thế này:
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
chỉ dành cho Postgres 9.6 trở lên.
Sử dụng kiểu đầu vào đa hình, kiểu này phù hợp với bất kỳ kiểu mảng, không chỉ int[]
.
Đặt nó thành IMMUTABLE
để cho phép tối ưu hóa hiệu suất và các biểu thức chỉ mục.
- PostgreSQL có hỗ trợ các ảnh ghép "không nhạy cảm với trọng âm" không?
Nhưng đừng làm cho nó STRICT
, điều này sẽ vô hiệu hóa "chức năng nội dòng" và làm giảm hiệu suất vì array_position()
không phải là STRICT
chinh no. Xem:
- Hàm thực thi nhanh hơn mà không có công cụ sửa đổi STRICT?
Nếu bạn cần nắm bắt trường hợp 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';
Đối với Postgres 9.1 sử dụng t_91
biểu thức từ trên xuống. Phần còn lại áp dụng không thay đổi.
Liên quan chặt chẽ:
- Làm cách nào để xác định xem NULL có được chứa trong một mảng trong Postgres hay không?