1

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

> 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

在启用的最后两行中false,我希望它是true

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

谢谢。

4

2 回答 2

4

您正在调用unnest3 次 onFROM子句,这意味着您正在执行 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)

对于任何版本,另一种选择是将调用添加到unnestinSELECT而不是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)

查看有关表函数调用的文档以获取更多信息。

于 2016-09-21T20:58:19.023 回答
4

您可以使用 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;

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

于 2016-09-21T20:56:58.230 回答