从 select 语句插入时如何使用 postgres Insert ....ON CONFLICT DO UPDATE

How to use postgres Insert ....ON CONFLICT DO UPDATE when inserting from select statement

我有以下 3 个 table。请原谅 table 名称,它们是通用数据库结构命名约定的一部分。

          table: tbl_331
          id (primary key, integer)
          field_3 (text)

          table: tbl_329_customid
          id (primary key, integer)
          fullname (text)

          table: tbl_331_to_tbl_329_field
          tbl_331_id (integer)
          tbl_329_id (integer)
          primary key (tbl_331_id, tbl_329_id)

我想编写一个查询,使用匹配值将值插入多对多 table: tbl_331_to_tbl_320_field。如果我使用 DO NOTHING 参数,这有效。

此语句用于插入它发现匹配的值。

    insert into schema_1.tbl_331_to_tbl_329_field_3 
    select  X.id, S.id from schema_1.tbl_329 S 
    JOIN schema_1.tbl_331_customid X on S.field_3=x.fullname
    ON CONFLICT DO NOTHING

但我想使用 DO UPDATE,所以如果有冲突,它会更新第二个 ID (S.id)。 例如,如果我将 S.field_3 中的值更改为与新 ID 匹配的某个其他值,我想更新此多对多 table.

中的 ID
   insert into schema_1.tbl_331_to_tbl_329_field_3 
    select  X.id, S.id from schema_1.tbl_329 S 
    JOIN schema_1.tbl_331_customid X on S.field_3=x.fullname
    ON CONFLICT ( tbl_331_id, tbl_329_id ) DO UPDATE set S.id = EXCLUDED.id

“这导致列‘id’的错误消息不明确。 “

如果我尝试使用这样的别名:

    insert into schema_1.tbl_331_to_tbl_329_field_3 
    select  X.id, S.id as myalias from schema_1.tbl_329 S 
    JOIN schema_1.tbl_331_customid X on S.field_3=x.fullname
    ON CONFLICT ( tbl_331_id, tbl_329_id ) DO UPDATE set S.id = myalias

我得到“myalias 列不存在”

我对 DO UPDATE 的这种语法很陌生。我的假设是,在 ON CONFLICT 之后,您必须指定它会发生冲突的 uniqye/primary 键,然后告诉它要更新什么。

我该如何编写才能更新匹配的新匹配 ID?

insert into schema_1.tbl_331_to_tbl_329_field_3 
select  X.id, S.id from schema_1.tbl_329 S 
JOIN schema_1.tbl_331_customid X on S.field_3=x.fullname
ON CONFLICT ( tbl_331_id, tbl_329_id ) DO UPDATE set S.id = EXCLUDED.id
  1. 这种类型的 UPDATE 的上下文只是那个名为 EXCLUDED 的特殊 table 本身。您的输入 table 在 UPDATE 中是不可见的,您只能看到您的冲突记录 (EXCLUDED) 和您试图将它们插入的字段([= 的列15=]).因此,您的 S 无法访问,也没有必要 - 在 ON CONFLICT ... DO UPDATE 中,您正在解决传入数据与目标 table 中已有数据之间的冲突 - Postgres 不介意你从哪里得到它,甚至不试图记住它。
  2. ERROR: column reference "id" is ambiguous 非常不直观。即使您可以随意为输入中的列添加别名——只要它们的顺序和类型与您的目标相匹配——在发生冲突时,它们会被处理,就好像它们已经在目标中一样 table。因此,您的第一个 id 和第二个 id(或稍后的 myalias)实际上已经在 EXCLUDED [=38] 中分别称为 tbl_331_idtbl_329_id =].您收到错误的原因是因为 Postgres 首先检查歧义 并立即在该点抛出错误,然后再检查这些列是否属于您当前的上下文。
  3. S.id = myalias 没有多大意义,因为它正是 S.id,您刚刚将其别名为 myalias.