【问题标题】:How to do an SQL UPDATE based on INSERT RETURNING id in Postgres?如何在 Postgres 中基于 INSERT RETURNING id 执行 SQL UPDATE?
【发布时间】:2018-09-20 15:46:05
【问题描述】:

我正在使用 Postgres。我有一张旧桌子和一张新桌子。旧表中的记录需要在新表中有相关​​记录。新表记录将有效地充当新表中记录的父级。

我正在尝试编写一个迁移,其中旧表中的每个“子”将在新表中具有“父”。

OLD TABLE(我添加了一个外键,希望在迁移过程中填充它)

 id | name | new_id (FK)
----+------+-------------
  1 | 1st  | 
  2 | 2nd  |

新表

 id | name 
----+------
    |

我需要做以下事情:

  • SELECT 旧表中的所有记录
  • INSERT 为每条旧记录和RETURNING id 新表中的一条记录
  • UPDATE 旧记录的外键值与RETURNING id

有没有办法使用集合查询来完成此任务?还是我需要开始深入研究 Postgres 的特定内容,例如 LOOPs?

【问题讨论】:

  • 您可以在 Postgres 中执行此操作。使用示例数据和结果,这个问题会更容易理解。
  • currval() 如果您知道序列名称,lastval() 用于序列中的最后一个插入,在原始行的每个循环中交替选择/插入/更新,或返回 id 方法。
  • @GordonLinoff 我添加了一些简化的表模式。
  • 我不太擅长 Postgres,但我想做一些研究。这个页面应该对你有很大帮助。 stackoverflow.com/questions/23382865/…

标签: sql postgresql migration database-migration


【解决方案1】:

您可以按如下方式使用可写 cte:

--open transaction
BEGIN;

--avoid concurrent writes
LOCK old_table IN ROW SHARE MODE;
LOCK new_table IN ROW SHARE MODE;

--create a sequence to populate new_table.id
CREATE SEQUENCE new_table_seq;

--using a writable cte to do the dirty job
WITH old_table_cte AS (
    UPDATE old_table SET new_id = nextval('new_table_seq') RETURNING *
)
INSERT INTO new_table SELECT new_id, name FROM old_table_cte;

--Create a proper FK
ALTER TABLE old_table ADD CONSTRAINT old_table_new_table_fk FOREIGN KEY (new_id) REFERENCES new_table (id);

--end transaction
COMMIT;

这种方法有一些好处:

  • 按照您的要求利用 RETURNING,但在 update 步骤中。避免不必要的 额外的选择;
  • 并发安全;
  • 推迟 FK 创建将导致更快的脚本;
  • 使用纯SQL解决方案,无需使用过程语言;
  • 避免在同一步骤读取和写入 old_table。

【讨论】:

    【解决方案2】:

    使用 TEMP 表执行迁移。在更新主表之前,我们应该根据需要在 TEMP 表上操作数据。

    【讨论】:

      【解决方案3】:

      这个页面应该可以帮助你:) postgreSQL function for last inserted ID

      INSERT INTO tableName (column1, column2) VALUES ('column1val', 'column2val') RETURNING id;
      

      然后您可以使用返回的 id 来更新原始行。您还可以使用该 SO 页面上建议的其他一些方法(下面提到/上面链接)

      currval() 如果您知道序列名称,lastval() 用于序列中的最后一个插入,在原始行的每个循环中交替选择/插入/更新,或返回 id 方法。

      【讨论】:

      • 我知道RETURNING id,但我需要对旧表中的每条记录执行此操作。这就是我应该如何遍历旧表中的记录的方式。
      • 你需要使用序列来做你想用 Postgresql 做的事情
      猜你喜欢
      • 2021-12-19
      • 2018-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-18
      相关资源
      最近更新 更多