如何在Postgres中基于插入返回id进行SQL更新?

如何在Postgres中基于插入返回id进行SQL更新?,sql,postgresql,migration,database-migration,Sql,Postgresql,Migration,Database Migration,我在用Postgres。我有一张旧桌子和一张新桌子。旧表中的记录需要在新表中有相关记录。新表记录实际上将充当新表中记录的父记录 我正在尝试编写一个迁移,其中旧表中的每个“子”将在新表中具有“父” 旧表(我添加了一个外键,以作为迁移的一部分填充它) 新表格 id | name ----+------ | 我需要做以下工作: 从旧表中选择所有记录 为每个旧记录在新表中插入一条记录,并返回id 使用返回的id更新旧记录的外键值 有没有一种方法可以使用集合查询来实现这一点?或者我需要开

我在用Postgres。我有一张旧桌子和一张新桌子。旧表中的记录需要在新表中有相关记录。新表记录实际上将充当新表中记录的父记录

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

旧表(我添加了一个外键,以作为迁移的一部分填充它)

新表格

 id | name 
----+------
    |
我需要做以下工作:

  • 从旧表中选择所有记录
  • 为每个旧记录在新表中插入一条记录,并
    返回id
  • 使用返回的id更新旧记录的外键值

有没有一种方法可以使用集合查询来实现这一点?或者我需要开始钻研Postgres的具体内容,比如
LOOP
s?

这一页应该可以帮助你:)

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


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

您可以使用可写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;
这种方法有一些好处:

  • update
    步骤中,利用按要求返回的优势。避免不必要的错误 额外选择
  • 并发安全
  • 延迟FK创建将导致更快的脚本
  • 采用纯SQL解决方案,无需使用过程语言
  • 避免在同一步骤中读取和写入旧的_表

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

您可以在Postgres中执行此操作。对于示例数据和结果,这个问题会更容易理解。currval()如果您知道序列名称,则lastval()表示序列中的最后一次插入,可以在原始行的每个循环中选择/插入/更新,也可以返回id方法。@GordonLinoff我添加了一些简化的表架构。我对Postgres不太擅长,但我想做一些研究。这一页应该对你有很大帮助。我知道
返回id
,但我需要对旧表中的每条记录执行此操作。这就是我应该如何迭代旧表中的记录,你需要使用序列来完成你想用Postgresql做的事情
INSERT INTO tableName (column1, column2) VALUES ('column1val', 'column2val') RETURNING id;
--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;