Postgres UPSERT 语法混乱

Posted

技术标签:

【中文标题】Postgres UPSERT 语法混乱【英文标题】:Postgres UPSERT syntax confusion 【发布时间】:2017-08-11 22:37:28 【问题描述】:

我有一个有 2 列的表: 频道文本 rowid 整数主键

我在频道中加入了索引 在 mytable 上创建唯一索引 channels_index (lower(channels))

这样 VisitToronto 将与 visittoronto 发生冲突

一切顺利,冲突开始了。 错误:重复键值违反唯一约束“channels_index” DETAIL: Key (lower(words))=(hello world) 已经存在。

我无法弄清楚捕获此冲突的语法。 ON CONFLICT 频道不起作用 ON CONFLICT ON CONSTRAINT channels_index 不起作用

我得到的最接近的是: 错误:没有符合 ON CONFLICT 规范的唯一或排除约束

任何方向都将不胜感激。

TIA

【问题讨论】:

【参考方案1】:

使用索引表达式,即lower(channels):

insert into my_table (channels) values
('VisitToronto');

insert into my_table (channels) 
values ('visittoronto')
on conflict (lower(channels)) do 
update set channels = excluded.channels;

select *
from my_table;

 id |   channels   
----+--------------
  1 | visittoronto
(1 row)

您无法使用约束,因为索引位于表达式上。在 Postgres 无法创建约束的情况下:

alter table my_table add constraint channels_unique unique using index channels_index;

ERROR:  index "channels_index" contains expressions
LINE 1: alter table my_table add constraint channels_unique unique u...
                                 ^
DETAIL:  Cannot create a primary key or unique constraint using such an index.

【讨论】:

非常感谢。我现在也理解了 Docs 的内容也好一点。有没有办法在不进行更新的情况下返回 channels_rowid?如果不是那没关系,我真的不在乎数据库中的哪个版本,主要是自学。我在更新语句之后使用'returning channels_rowid',该语句为插入和更新都返回,但如果我“不做任何事情”它不会返回,如果我使用 SELECT 我会收到错误 很遗憾,您无法从do nothing 返回任何内容,因为没有任何行受到影响。你需要一个函数来完成这个。

以上是关于Postgres UPSERT 语法混乱的主要内容,如果未能解决你的问题,请参考以下文章

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

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

Postgres UPSERT (INSERT 或 UPDATE) 仅当值不同时

使用 upsert 和多语法更新 Mongodb

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

SQL Server 中单行 MERGE / upsert 的语法