(POSTGRES) ON CONFLICT ... WHERE 条件似乎不起作用

Jes*_*ica 3 postgresql query

我们正在尝试使用旧表中的信息为新功能填充新表,但我们将多次将此查询作为脚本运行,因为我们想要捕获任何用户更新的数据。

表 1 架构。

table1
id | email | first_name | last_name | job | phone | user_id | institution_id | institution_type | completion_state | created_at | updated_at | mobile_phone | deleted_at
----+-------+------------+-----------+-----+-------+---------+----------------+------------------+------------------+------------+------------+--------------+------------
Run Code Online (Sandbox Code Playgroud)

表 2 架构。

table2
 id | contact_id | status | data | created_at | updated_at | source_updated_at
----+------------+--------+------+------------+------------+-------------------
Run Code Online (Sandbox Code Playgroud)

这是我的查询


INSERT INTO table2 AS iic (contact_id, data, created_at, updated_at, source_updated_at)
SELECT
  cc.id,
  (
  SELECT row_to_json(_) FROM (
    SELECT
      cc.email,
      cc.first_name,
      cc.last_name,
      cc.job,
      cc.phone,
      cc.user_id,
      cc.institution_id,
      cc.institution_type,
      cc.completion_state,
      cc.updated_at,
      cc.mobile_phone,
      inst.type,
      inst.name,
      inst.description,
      inst.assets_under_management,
      inst.phone,
      add.id,
      add.street,
      add.street2,
      add.city,
      add.state,
      add.country,
      add.zip_code
      ) AS _
    ) AS data,
  current_timestamp,
  current_timestamp,
  cc.updated_at
FROM table1 cc
LEFT JOIN institutions inst
  ON cc.institution_id = inst.id
LEFT JOIN addresses add 
  ON add.addressable_id = inst.id
ON CONFLICT (contact_id) DO
  UPDATE SET status = 'updated',
             source_updated_at = excluded.updated_at
  WHERE iic.source_updated_at != excluded.updated_at;
Run Code Online (Sandbox Code Playgroud)

因此,我们将表 1 的信息复制到表 2 中。我们第一次运行它时,一切都完美地复制过来,状态列为空。如果我然后更改 table1 上单行的更新日期,我希望

ON CONFLICT ... UPDATE
Run Code Online (Sandbox Code Playgroud)

只会在 updated_at 行发生更改的情况下触发和更新 table2。相反,它将 table2 上的所有状态更改为已更新。

我怀疑 WHERE 子句不是特定于行的,而是适用于更大的集合,在这种情况下,此条件将始终返回 true。但是,如果有人可以阐明我如何修改我的查询以返回我正在寻找的内容,那就太好了。

如果有任何需要澄清的地方,请告诉我。

干杯,

postgres v.9.6.11

Jes*_*ica 8

在@a_horse_with_no_name 的帮助下,我能够在我的想法中找到错误。PostgresSQL文档中有一个很好的例子,它真正为我澄清了这一点:

根据需要插入或更新新的经销商。假设已定义唯一索引来限制出现在 did 列中的值。请注意,特殊排除表用于引用最初建议插入的值:

INSERT INTO distributors (did, dname)
    VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
    ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;
Run Code Online (Sandbox Code Playgroud)

我最初的想法是该EXCLUDED表使用了与我试图从中插入的表相同的列名。实际上,它引用了我试图插入的表的列名,但这些值是最初建议插入的。

所以,我的查询的结尾应该是这样的:

...
ON CONFLICT (contact_id) DO
  UPDATE SET status = 'updated',
             source_updated_at = EXCLUDED.source_updated_at
  WHERE iic.source_updated_at != EXCLUDED.source_updated_at;
Run Code Online (Sandbox Code Playgroud)

感谢您成为我的橡皮鸭,我希望这可以帮助其他人!