sql - PostgreSQL - CTE upsert 返回修改后的行

标签 sql postgresql postgresql-9.1 common-table-expression upsert

我使用 CTE 编写了一个“upsert”查询,看起来像这样:

WITH
  new_data (id, value) AS (
    VALUES (1, 2), (3, 4), ...
  ),
  updated AS (
    UPDATE table t set
      value = t.value + new_data.value
    FROM new_data
    WHERE t.id = new_data.id
    RETURNING t.*
  )
INSERT INTO table (id, value)
  SELECT id, value
  FROM new_data
  WHERE NOT EXISTS (
    SELECT 1 FROM updated WHERE updated.id = new_data.id
  )

然而,我随后需要在我的应用程序中使用新值,但此查询不会返回任何内容。在插入的末尾添加 returning * 将返回所有已插入的行,但不会返回任何已更新的行。

所以,问题是(如何)扩展它以返回更新的行和插入的行?

编辑: 当然,我可以在事务中运行它,然后执行 SELECT,但是我很想知道是否有单一查询方式。

最佳答案

尝试这样的事情:

WITH
  new_data (id, value) AS (
    VALUES (1, 2), (3, 4), ...
  ),
  updated AS (
    UPDATE table t set
      value = t.value + new_data.value
    FROM new_data
    WHERE t.id = new_data.id
    RETURNING t.*
  ),
  inserted as (
  INSERT INTO table (id, value)
  SELECT id, value
  FROM new_data
  WHERE NOT EXISTS (
    SELECT 1 FROM updated WHERE updated.id = new_data.id
  )
  RETURNING id, value)
SELECT id, value
FROM inserted 
UNION ALL
SELECT id, value
FROM updated 

顺便说一句,这个查询不是经典的 Postgres upsert。如果有人在 UPDATE table t 进行时同时插入行,它将失败。

关于sql - PostgreSQL - CTE upsert 返回修改后的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17575489/

相关文章:

database - 更新 postgres 表以压缩第二个表中的重复值

regex - 在 postgreSQL 中使用正则表达式验证列

postgresql - 如何修复postgresql服务器自动重启

java - 简单 JPA 到 Postgresql 9.1 HibernateEx

sql - 如何为动态生成 Select 语句的 30 列表创建索引

用于列出 SQL Server 2005 数据库中所有 View 的 Sql 查询

mysql - 优化运行时间约为 30 秒的 MySQL 查询

sql - 如何编写查询/创建 View 以限制多条记录仅显示最大值

Django-celery 任务和 django 事务

sql - 如何在条件下仅将一些 Guids 从一个表替换为另一个表