Cau*_*tic 6 postgresql syntax update upsert
我有一个查询,当一个键冲突时,只有在其他列之一发生更改时才会向上插入 Postgres(以避免不必要的插入和返回的行,但实际上没有任何更改):
INSERT INTO public.test_upsert (some_id, a, b, note)
VALUES
('c', 1, true, 'asdf')
ON CONFLICT (some_id)
DO UPDATE SET
a = excluded.a,
b = excluded.b,
note = excluded.note
WHERE
test_upsert.a IS DISTINCT FROM excluded.a OR
test_upsert.b IS DISTINCT FROM excluded.b OR
test_upsert.note IS DISTINCT FROM excluded.note
RETURNING *;
Run Code Online (Sandbox Code Playgroud)
我的问题是:这个有简写吗?我基本上想在插入的任何列与现有列不同时插入新记录更新行。单独写出每一列会变得非常冗长,尽管它更明确。
SQL 中没有规定说“除了这一列之外的所有列”。(您可以使用jsonb
或来做类似的事情hstore
。) 相关答案的详细信息:
再想一想,你不需要这个。您不妨更新所有列。无论如何,Postgres 都会写一个新的行版本,没有任何损失。
INSERT INTO test_upsert AS t (some_id, a, b, note) -- list is optional
VALUES ('c', 5, true, 'asdf')
ON CONFLICT (some_id)
DO UPDATE
SET (some_id, a, b, note) = ROW (excluded.*) -- ROW syntax
WHERE (t.*) IS DISTINCT FROM (excluded.*) -- again, compare whole row
RETURNING *;
Run Code Online (Sandbox Code Playgroud)
您仍然需要为 的目标列表拼写一次列列表SET
。这是必需的。其余的可以缩短。
INSERT
无论如何,您甚至可以暂时忽略目标列表,同时针对所有列,但在大多数情况下,最好将其拼写出来,这样可以更有效地应对未来的变化。
表别名是可选的附加语法速记。请注意,与AS
表别名的INSERT
大多数地方不同,目标的表别名需要关键字。
或者更短,但是:
...
WHERE t IS DISTINCT FROM excluded
...
Run Code Online (Sandbox Code Playgroud)
我们也可以只使用表名(或别名)作为(众所周知的!)复合类型。唯一的极端情况的缺点是:如果还有一个同名的列“t”(或“排除”),由于 Postgres 语法规则,它优先。(t.*) IS DISTINCT FROM (excluded.*)
不会弄错,是稍微安全一点的形式。相关回答:
归档时间: |
|
查看次数: |
580 次 |
最近记录: |