Postgres UPSERT - 如果所有数据都相同,请不要更新?

Posted

技术标签:

【中文标题】Postgres UPSERT - 如果所有数据都相同,请不要更新?【英文标题】:Postgres UPSERT - don't update if all data the same? 【发布时间】:2017-06-30 10:32:51 【问题描述】:

我正在使用 Postgres 9.6。如果关于它的 anything 不同,我想更新记录,但如果没有,则保持相同。

这是我的 SQL,略微简化,因为我的表实际上有更多字段(通过 psycopg2 运行):

query = "INSERT INTO cap(scheme, year, code) "
query += "VALUES(%s, %s, %s) "
query += "ON CONFLICT DO NOTHING"
cursor.execute(query, ('abc', 2015, 'twu'))

但是,如果我使用完全相同的值运行它两次,我会在数据库中获得两条记录。

如何修改此查询,以便提供完全相同的值不会创建新记录?

我尝试阅读ON CONFLICT UPDATE documentation,但不知道如何根据我的情况进行调整。特别是,在我看来 DO NOTHING 不应该插入一行(文档说:“ON CONFLICT DO NOTHING 只是避免插入一行作为其替代操作”),但它确实插入了一个新行。

【问题讨论】:

您是否为该表定义了主键或唯一键? edit您的问题并为表cap添加完整的create table语句(包括所有索引) 【参考方案1】:

INSERT ... ON CONFLICT ... 需要一个唯一的约束来捕捉冲突,例如

create table cap(
    scheme text, 
    year int, 
    code text, 
    unique(scheme, year, code) -- ! added
);

使用唯一约束多次执行此查询

INSERT INTO cap(scheme, year, code)
VALUES('abc', 2015, 'twu')
ON CONFLICT DO NOTHING

将只插入该行一次。

【讨论】:

以上是关于Postgres UPSERT - 如果所有数据都相同,请不要更新?的主要内容,如果未能解决你的问题,请参考以下文章

sql Comando UPSERT(postgres)

使用 python 对 postgres 执行 upsert 操作,如 pandas to_sql 函数

Postgres UPSERT 语法混乱

SQLAlchemy Upsert无法找到表“已排除”

无法使用 upsert 删除键

如何使用柴油在 sqlite 中进行 upsert?