【问题标题】:Use INSERT ... ON CONFLICT DO NOTHING RETURNING failed rows使用 INSERT ... ON CONFLICT DO NOTHING RETURNING 失败的行
【发布时间】:2018-03-06 21:16:21
【问题描述】:

假设我有下表:

CREATE TABLE tags (
    id int PK,
    name varchar(255),
    CONSTRAINT name_unique UNIQUE(name)
)

我需要一个查询来插入不存在的标签并返回所有请求标签的 ID。考虑以下几点:

INSERT INTO tags (name) values ('tag10'), ('tag6'), ('tag11') ON CONFLICT DO NOTHING returning id, name

这个查询的输出是:

+---------------+
|  id   |  name |
|---------------|
|  208  | tag10 |
|---------------|
|  209  | tag11 |
+---------------+

我需要在输出中有tag6

【问题讨论】:

  • 不相关,但是:您是否知道 varchar 列的长度 255 与 254 或 300 相比没有性能或存储优势?
  • @a_horse_with_no_name 更好地解释一下...我来这里只是为了我的业务,​​但您的评论唤醒了我的好奇心...
  • 长度 255 没有内置的“魔法”,如果这是您的想法。没有秘密优化可以使声明为varchar(255) 的列比定义为varchar(300) 的列更“有效”。每次我看到“幻数” 255 时,我都会质疑 为什么 选择了这个 - 尤其是 Postgres 在性能 方面绝对没有差异在varchar(1)、varchar(78656)` 和text 之间(当您只存储一个字符时)。您需要将长度定义视为业务约束,而不是技术“事物”
  • @a_horse_with_no_name 我认为varchar(255) 源于Oracle。 (我似乎确实记得 Postgres 中较小的 varchar 列没有被烘烤)
  • @joop:Oracle 从未对varchar(255) 进行过任何优化(至少自 8i 以来没有)。并且决定是否在 Postgres 中烘烤(=压缩)值不是根据列 definition 而是根据存储在其中的值的实际长度来决定的

标签: postgresql postgresql-9.5


【解决方案1】:

有点冗长,但我想不出别的:

with all_tags (name) as (
  values ('tag10'), ('tag6'), ('tag11')
), inserted (id, name) as (
   INSERT INTO tags (name)
   select name 
   from all_tags
   ON CONFLICT DO NOTHING 
   returning id, name
)
select t.id, t.name, 'already there'
from tags t
  join all_tags at on at.name = t.name
union all
select id, name, 'inserted'
from inserted;

来自tags 的外部选择会看到表格的快照,因为它是在插入新标签之前。带有常量的第三列仅用于测试查询,以便识别插入了哪些行,哪些没有插入。

【讨论】:

  • 谢谢。我得到syntax error at or near "id" LINE 3: ), inserted as (id, name)
  • 它可以满足我的需要。非常感谢!
【解决方案2】:

有了这张桌子:

CREATE TABLE tags (
    id serial PRIMARY KEY,
    name text UNIQUE
);

只要查询中的值是唯一的,解决方法就是:

INSERT INTO tags (name) 
VALUES ('tag10'), ('tag6'), ('tag11') 
ON CONFLICT DO UPDATE name = EXCLUDED.name RETURNING id, name;

【讨论】:

  • 我认为作为 MVCC 的一部分,即使您要更新的值相同,此更新也会触发磁盘写入 - 在生产环境中需要注意这一点。
猜你喜欢
  • 2019-09-20
  • 1970-01-01
  • 2018-08-02
  • 2021-11-02
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
相关资源
最近更新 更多