【问题标题】:PostgreSQL - Update an array's values to the distinct union of its elements and elements of another arrayPostgreSQL - 将数组的值更新为其元素和另一个数组元素的不同联合
【发布时间】:2020-03-24 11:36:05
【问题描述】:

我遇到了一个问题,用另一个数组中不存在的值更新数组的元素。

具体来说,考虑下表tbl1,它看起来有点像这样:

+-----------------------------------+
|   c1  |   c2  |   c3  |   c4      |
+-----------------------------------+
|   A   |   B   |   C   | [1, 2, 3] |
|-----------------------------------|

假设我想使用以下数据更新列c4[2, 3, 4]。 我希望c4 的更新值为[1, 2, 3, 4]

到目前为止,我尝试了以下方法:

INSERT INTO 
    tbl1 (
        c1, c2, c3, c4
    ) 
VALUES ....
ON CONFLICT (c1, c2) DO UPDATE
SET c3=EXCLUDED.c3,
    c4=(SELECT ARRAY_AGG(x ORDER BY x) FROM (SELECT DISTINCT UNNEST(ARRAY_CAT(c4, EXCLUDED.c4)) AS x) AS s)

但是,查询似乎不合法。 执行时出现语法错误,指出我不能在 SET 语句中使用 SELECT

我也有几个限制:

  1. 我必须更新值on conflict
  2. 我无法在数据库中创建辅助函数
  3. 必须是单个查询

【问题讨论】:

    标签: sql arrays postgresql


    【解决方案1】:

    试试这个:

    CREATE TABLE Foo(id INT primary key, arr int[]);
    INSERT INTO Foo(id, arr) values (1, array[1,2,3]);
    
    INSERT INTO Foo(id, arr) VALUES (1, ARRAY[2,3,4]) 
    ON CONFLICT (id) 
    DO UPDATE SET arr = (
      with T AS (
        -- Make a table out of existing array value
        SELECT unnest(arr) FROM Foo WHERE id=EXCLUDED.id
      ), S AS (                        
        -- Make a table out of new array    
        SELECT unnest(EXCLUDED.arr)
      ),                                
      -- Union both tables and aggregate back to array
      R AS (
        SELECT array_agg(unnest) AS arr FROM (
          SELECT * FROM T UNION SELECT * FROM S
        ) U
      )
      SELECT arr FROM R
    );
    

    【讨论】:

      【解决方案2】:

      这对我有用:

      insert into the_table (c1,c2,c3,c4)
      values ('A', 'B', 'new', array[2,3,4])
      on conflict (c1,c2)
       do update set 
           c3 = excluded.c3, 
           c4 = (select array_agg(distinct x order by x) 
                 from unnest(the_table.c4||excluded.c4) as t(x))
      ;
      

      Online example

      INSERT 部分中的null 值使原始数组保持不变,因为array[1,2,3]||null::int[] 产生{1,2,3}。如果您不希望这样,您可能需要在更新部分添加一些 CASE 表达式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-06
        • 2021-06-02
        • 1970-01-01
        • 2013-11-02
        • 1970-01-01
        • 1970-01-01
        • 2023-01-18
        • 2013-11-08
        相关资源
        最近更新 更多