如何在不创建新行的情况下更新 table
How to update a table without creating new rows
假设我有一组从主键到值的键值数据:
id
foo
1
abc
2
def
3
ghj
...需要在 table.
中更新
我想在一个查询中更新所有这些。自然而然地,upserts 浮现在脑海中,效果很好:
INSERT INTO my_table (id, foo) VALUES ((1, 'abc'), (2, 'def'), (3, 'ghj'))
ON CONFLICT (id) DO UPDATE SET foo = excluded.foo;
这很好用,但是如果我实际上不想插入 id=3 的行,因为它不存在于 table my_table
中怎么办?
我已经尝试过(并且有效)的一件事是使用源查询,它接收所有源数据作为 json 列表,然后内部连接到现有的 table 到丢弃所有在 my_table
:
中没有条目的记录
[
{"id": 1, "foo": "abc"},
{"id": 2, "foo": "def"},
{"id": 3, "foo": "ghj"}
]
作为此查询的唯一参数传递:
WITH source AS (
SELECT my_table.id, x.foo FROM jsonb_to_recordset(::jsonb) AS x(id int, foo text)
JOIN my_table ON x.id = my_table.id
)
INSERT INTO my_table (id, foo)
(SELECT * FROM source)
ON CONFLICT(id) DO UPDATE SET foo = excluded.foo
如果您只想更新行,我完全不明白为什么您需要 INSERT?
update my_table
set foo = v.foo
from (
VALUES (1, 'abc'), (2, 'def'), (3, 'ghj')
) as v(id, foo)
where v.id = my_table.id;
假设我有一组从主键到值的键值数据:
id | foo |
---|---|
1 | abc |
2 | def |
3 | ghj |
...需要在 table.
中更新我想在一个查询中更新所有这些。自然而然地,upserts 浮现在脑海中,效果很好:
INSERT INTO my_table (id, foo) VALUES ((1, 'abc'), (2, 'def'), (3, 'ghj'))
ON CONFLICT (id) DO UPDATE SET foo = excluded.foo;
这很好用,但是如果我实际上不想插入 id=3 的行,因为它不存在于 table my_table
中怎么办?
我已经尝试过(并且有效)的一件事是使用源查询,它接收所有源数据作为 json 列表,然后内部连接到现有的 table 到丢弃所有在 my_table
:
[
{"id": 1, "foo": "abc"},
{"id": 2, "foo": "def"},
{"id": 3, "foo": "ghj"}
]
作为此查询的唯一参数传递:
WITH source AS (
SELECT my_table.id, x.foo FROM jsonb_to_recordset(::jsonb) AS x(id int, foo text)
JOIN my_table ON x.id = my_table.id
)
INSERT INTO my_table (id, foo)
(SELECT * FROM source)
ON CONFLICT(id) DO UPDATE SET foo = excluded.foo
如果您只想更新行,我完全不明白为什么您需要 INSERT?
update my_table
set foo = v.foo
from (
VALUES (1, 'abc'), (2, 'def'), (3, 'ghj')
) as v(id, foo)
where v.id = my_table.id;