【问题标题】:How to determine if NULL is contained in an array in Postgres?如何确定 NULL 是否包含在 Postgres 的数组中?
【发布时间】:2014-05-06 20:43:04
【问题描述】:

如何确定 NULL 是否包含在 Postgres 中的数组中?目前使用 Postgres 9.3.3。

如果我使用以下选择进行测试,它将返回 contains_null = false

select ARRAY[NULL,1,2,3,4,NULL]::int[] @> ARRAY[NULL]::int[] AS contains_null select ARRAY[NULL,1,2,3,4,NULL]::int[] @> NULL AS contains_null

我也试过:

  1. @>(包含)
  2. &&(重叠)

【问题讨论】:

  • 这个类似问题下的更多解决方案:stackoverflow.com/questions/34848009/…
  • create table scientist (id integer, firstname varchar(100), lastname varchar(100)); insert into scientist (id, firstname, lastname) values (1, 'albert', 'einstein'); insert into scientist (id, firstname, lastname) values (2, 'isaac', 'newton'); insert into scientist (id, firstname, lastname) values (3, 'marie', null); select * from scientist where lastname is null or lastname in ('einstein', 'newton', null);。我试过这个,但是选择查询没有在这里返回null 条目。所以,我认为,这就是它的工作原理,数组中的null 将不起作用。

标签: sql arrays postgresql


【解决方案1】:
select exists (
    select 1 
    from unnest(array[1, null]) s(a)
    where a is null
);
 exists 
--------
 t

或更短:

select bool_or(a is null)
from unnest(array[1, null]) s(a)
;
 bool_or 
---------
 t

【讨论】:

  • 有没有比使用 unnest 更好的方法?我已经考虑过这一点,但是有 1+ 百万条记录,其中一列可能有 30 多个数组项,unnest 会产生相当多的记录。这是一个审计表。
  • @thames 我认为 unnest 会表现得很好,我不知道还有其他方法。
【解决方案2】:

理想情况下你会写:

SELECT
    NULL IS NOT DISTINCT FROM ANY ARRAY[NULL,1,2,3,4,NULL]::int[];

但解析器无法将 IS NOT DISTINCT FROM 识别为此处运算符的有效语法,我找不到它的运算符别名。

你必须:

CREATE FUNCTION opr_isnotdistinctfrom(anyelement, anyelement)
RETURNS boolean LANGUAGE SQL IMMUTABLE AS $$
SELECT $1 IS NOT DISTINCT FROM $2; 
$$;

CREATE OPERATOR <<>> (
    PROCEDURE = opr_isnotdistinctfrom,
    LEFTARG = anyelement,
    RIGHTARG = anyelement
);

SELECT NULL <<>> ANY (ARRAY[NULL,1,2,3,4,NULL]::int[]);

这看起来有点可怕,但应该优化出来就好了。

【讨论】:

    【解决方案3】:

    我也不想使用unnest,所以我使用array_lengtharray_remove 的比较来解决类似的问题。在 9.4.1 上测试,但应该在 9.3.3 中工作。

    SELECT
    ARRAY_LENGTH(ARRAY[1,null], 1) > ARRAY_LENGTH(ARRAY_REMOVE(ARRAY[1,null], NULL), 1) 
    OR ARRAY_LENGTH(ARRAY_REMOVE(ARRAY[1,null], NULL), 1) IS NULL
    ---------
    t
    

    【讨论】:

      【解决方案4】:

      还有一个构造,例如 @Clodoaldo Neto 提出的。更简洁的表达方式:

      CREATE TEMPORARY TABLE null_arrays (
            id serial primary key
          , array_data int[]
      );
      
      INSERT INTO null_arrays (array_data)
      VALUES
            (ARRAY[1,2, NULL, 4, 5])
          , (ARRAY[1,2, 3, 4, 5])
          , (ARRAY[NULL,2, 3, NULL, 5])
      ;
      
      SELECT 
          *
      FROM 
          null_arrays
      WHERE
          TRUE = ANY (SELECT unnest(array_data) IS NULL)
      ;
      

      【讨论】:

        【解决方案5】:

        以下似乎在 PostgreSQL 10.1 中运行良好。

        CREATE TABLE my_table
        (
            ...
            my_set  int[] NOT NULL,
            ...
        );
        
        SELECT
            my_set
        FROM
            my_table
        WHERE
            array_position(my_set, NULL) IS NOT NULL;
        

        【讨论】:

          【解决方案6】:

          这是一个可重用的功能:

          CREATE OR REPLACE FUNCTION f_check_no_null (anyarray)
            RETURNS bool LANGUAGE sql IMMUTABLE AS
           'SELECT CASE WHEN $1 IS NOT NULL THEN array_position($1, NULL) IS NULL END';
          

          然后您可以在检查约束中使用它:

          CREATE TABLE foo (
            array_with_no_nulls TEXT[] NOT NULL CHECK(f_check_no_null(array_with_no_nulls))
          );
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-11-10
            • 2020-10-10
            • 2014-11-15
            • 2019-02-12
            • 2014-02-23
            • 1970-01-01
            相关资源
            最近更新 更多