PostgreSQL INSERT ON CONFLICT UPDATE (upsert) 使用所有排除值

Posted

技术标签:

【中文标题】PostgreSQL INSERT ON CONFLICT UPDATE (upsert) 使用所有排除值【英文标题】:PostgreSQL INSERT ON CONFLICT UPDATE (upsert) use all excluded values 【发布时间】:2016-07-21 10:39:12 【问题描述】:

当您更新一行时 (PostgreSQL >= 9.5),并且您希望可能的 INSERT 与可能的 UPDATE 完全相同,您可以这样写:

INSERT INTO tablename (id, username, password, level, email) 
                VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') 
ON CONFLICT (id) DO UPDATE SET 
  id=EXCLUDED.id, username=EXCLUDED.username,
  password=EXCLUDED.password, level=EXCLUDED.level,email=EXCLUDED.email

有没有更短的方法?只是说:使用所有 EXCLUDE 值。

在 SQLite 中我曾经这样做过:

INSERT OR REPLACE INTO tablename (id, user, password, level, email) 
                        VALUES (1, 'John', 'qwerty', 5, 'john@mail.com')

【问题讨论】:

不是一个真正的答案,但您可以使用略短的符号:INSERT INTO tablename (id, username, password, level, email) VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') ON CONFLICT (id) DO UPDATE SET (username, password, level, email) = (EXCLUDED.username, EXCLUDED.password, EXCLUDED.level, EXCLUDED.email). 几乎相同,但易于复制/粘贴/管理列列表 另一种选择是使用 jsonb 列,这样您就不必担心列 @foal 作为答案发布,这是一个非常有用的选择。 【参考方案1】:

Postgres 尚未实现与INSERT OR REPLACE 等效的功能。来自ON CONFLICT docs(强调我的):

它可以是 DO NOTHING 或 DO UPDATE 子句,指定在发生冲突时要执行的 UPDATE 操作的确切细节

虽然它没有为您提供替换的简写,但ON CONFLICT DO UPDATE 更普遍适用,因为它允许您根据预先存在的数据设置新值。例如:

INSERT INTO users (id, level)
VALUES (1, 0)
ON CONFLICT (id) DO UPDATE
SET level = users.level + 1;

【讨论】:

您能否详细说明“但插入中的确切问题并未导致更新”? @pojo-guy - 我认为您没有看到 MrR 提出的问题 - 您能否扩展“但插入中的确切问题并未导致更新”? 当您尝试在 postgresql 中使用 insert ... on update 时,在某些特定情况下结果与合并不同。我遇到的案例相当晦涩和具体,但可以重复。已经几个月了,所以我现在不能再给了。 也许不是冲突,而是另一个错误,例如字段类型错误?

以上是关于PostgreSQL INSERT ON CONFLICT UPDATE (upsert) 使用所有排除值的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql EXCLUDE 约束在 INSERT 时未触发 ON CONFLICT

如何在 flask_sqlalchemy 中使用 PostgreSQL 的“INSERT...ON CONFLICT”(UPSERT)功能?

如何将 DELETE 的返回值插入到 postgresql 中的 INSERT 中?

Postgresql 日志收集

postgresql----INSERT

mysql_insert_id 替代 postgresql