【问题标题】:Bulk update in postgreSQL using unnest使用 unnest 在 postgreSQL 中批量更新
【发布时间】:2016-09-21 20:36:46
【问题描述】:

我正在尝试进行批量更新:

> update ti_table set enabled=T.enabled 
    from (select * from 
         unnest(array['2001622', '2001624', '2007903']) as id,
         unnest(array[15,14,8]) as ver,
         unnest(array['type1', 'type1', 'type1']) as type,
         unnest(array[false, true, true]) as enabled) T 
    where ti_table.id=T.id AND ti_table.ver=T.ver AND ti_table.type=T.type;

但是,当我回读时:

> select id, ver, type, enabled from ti_table where id in ('2001622', '2001624', '2007903');

我明白了:

   id    | ver | type  | enabled 
---------+-----+-------+---------
 2001622 |  15 | type1 | f
 2001624 |  14 | type1 | f
 2007903 |   8 | type1 | f

在最后两行 enabledfalse 而我预计它是 true

为什么会发生这种情况,我该如何正确地做到这一点?

谢谢。

【问题讨论】:

  • 嗯,您正在更新ti_table 并回读ti_rules
  • 子查询似乎返回了 81 个结果(3*3*3*4)...显然每个 unnest 为每个值返回一个集合...
  • @MatheusOl 我修正了这是一个错字。问题是内部选择执行笛卡尔积,而不是为具有相同索引的每组值创建单行。

标签: postgresql bulkupdate


【解决方案1】:

您在 FROM 子句上调用了 3 次 unnest,这意味着您正在执行 3 的 CROSS JOIN(笛卡尔积)。

如果您使用的是 PostgreSQL 9.4 或更高版本,您可以简单地调用一次 unnest,将每个数组作为输入:

select * from 
         unnest(
            array['2001622', '2001624', '2007903'],
             array[15,14,8],
             array['type1', 'type1', 'type1'],
             array[false, true, true]
        ) as u(id, ver, type, enabled)

对于任何版本,另一种选择是在SELECT 中添加对unnest 的调用,而不是FROM

select
   unnest(array['2001622', '2001624', '2007903']) as id,
   unnest(array[15,14,8]) as ver,
   unnest(array['type1', 'type1', 'type1']) as type,
   unnest(array[false, true, true]) as enabled

在这两种情况下,尤其是在最后一种情况下,您必须确保每个数组具有完全相同数量的元素。如果它不在第一个方法上,每个缺失的行将被填充为 NULL,但第二个它将返回与每个返回的行数的 LCM 一样多的行,这是您可能不想要的。示例:

SELECT * FROM unnest(array[1,2,3,4], array['a','b','c','d','e','f']);
 unnest | unnest 
--------+--------
      1 | a
      2 | b
      3 | c
      4 | d
 [null] | e
 [null] | f
(6 rows)

SELECT unnest(array[1,2,3,4]), unnest(array['a','b','c','d','e','f']);
 unnest | unnest 
--------+--------
      1 | a
      2 | b
      3 | c
      4 | d
      1 | e
      2 | f
      3 | a
      4 | b
      1 | c
      2 | d
      3 | e
      4 | f
(12 rows)

查看table functions calls 上的文档了解更多信息。

【讨论】:

    【解决方案2】:

    您可以使用 PostgreSQL VALUES

    UPDATE ti_table ti
    SET enabled = data.enabled
    FROM (
      VALUES
        ('2001622', 15, 'type1', false),
        ('2001624', 14, 'type1', true),
        ('2007903', 8, 'type1', true)
    ) AS data(id, ver, type, enabled)
    WHERE ti.id = data.id
    AND ti.ver = t.ver
    AND ti.type = data.type;
    

    它更易于阅读,因为值按行分组在一起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      • 2015-07-21
      • 2021-03-11
      相关资源
      最近更新 更多