使用不正确的

时间:2016-09-21 20:36:46

标签: postgresql bulkupdate

我正在尝试批量更新:

> 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

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

感谢。

2 个答案:

答案 0 :(得分:3)

您在unnest条款上调用FROM 3次,这意味着您正在执行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)

对于任何版本,另一个选项是将调用添加到unnest而不是SELECT中的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上的文档以获取更多信息。

答案 1 :(得分: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;

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