使用 unnest 在 postgreSQL 中批量更新
Bulk update in postgreSQL using unnest
我正在尝试进行批量更新:
> 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
最后两行 enabled 是 false
而我预计它是 true
为什么会发生这种情况,我该如何正确处理?
谢谢。
您可以使用 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;
它更易于阅读,因为值按行分组在一起。
您在 FROM
子句上调用了 unnest
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)
对于任何版本,另一个选项是在 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,但第二个方法将 return 行数与 returned 行数的 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 上的文档以获取更多信息。
我正在尝试进行批量更新:
> 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
最后两行 enabled 是 false
而我预计它是 true
为什么会发生这种情况,我该如何正确处理?
谢谢。
您可以使用 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;
它更易于阅读,因为值按行分组在一起。
您在 FROM
子句上调用了 unnest
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)
对于任何版本,另一个选项是在 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,但第二个方法将 return 行数与 returned 行数的 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 上的文档以获取更多信息。