[英]How to do an SQL UPDATE based on INSERT RETURNING id in Postgres?
I'm using Postgres. 我正在使用Postgres。 I have an old table and a new table. 我有一张旧桌子和一张新桌子。 The records in the old table need to have related records in the new table. 旧表中的记录需要在新表中具有相关记录。 The new table records are effectively going to act as the parents for records in the new table. 新表记录将有效地充当新表中记录的父级。
I'm trying to write a migration where each "child" from the old table will have "parent" in the new table. 我正在尝试编写一个迁移,其中旧表中的每个“子”在新表中都将有“父”。
OLD TABLE (I've added a foreign key in anticipation of populating it as part of the migration) OLD TABLE (我已经添加了一个外键,以期将其作为迁移的一部分进行填充)
id | name | new_id (FK)
----+------+-------------
1 | 1st |
2 | 2nd |
NEW TABLE 新表
id | name
----+------
|
I need to do the following: 我需要执行以下操作:
SELECT
all records from the old table SELECT
旧表中的所有记录 INSERT
a record into the new table for each old record and RETURNING id
INSERT
记录到新表中的每个旧记录和RETURNING id
UPDATE
the old record's foreign key value with the RETURNING id
使用RETURNING id
UPDATE
旧记录的外键值 Is there a way to accomplish this using a set query? 有没有一种方法可以使用设置查询来完成此任务? Or do I need to start delving into Postgres specific things like LOOP
s? 还是我需要开始研究诸如LOOP
的Postgres特定内容?
You can use a writable cte as follows: 您可以按以下方式使用可写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;
This approach has some benefits: 这种方法有一些好处:
update
step. 根据您的要求利用RETURNING的优势,但要进行update
。 Avoiding an unnecessary extra SELECT; 避免不必要的额外SELECT; This page should help you out :) postgreSQL function for last inserted ID 该页面应该可以帮助您:) 最后插入的ID的postgreSQL函数
INSERT INTO tableName (column1, column2) VALUES ('column1val', 'column2val') RETURNING id;
You can then use the returned id to update the original row. 然后,您可以使用返回的ID更新原始行。 You can also use a few other methods suggested on that SO page (mentioned below / linked above) 您还可以使用该SO页上建议的其他几种方法(如下所述/上面链接)
currval() if you know sequence name, lastval() for last insert in sequence, to alternate between select/insert/update in each loop for original rows, or RETURNING id method. currval()(如果您知道序列名称),lastval()(用于序列中的最后一个插入),在每个循环中为原始行在选择/插入/更新之间交替或返回ID方法。
Use TEMP Table to perform migration. 使用TEMP表执行迁移。 Before update on main table, we should manipulate data over TEMP table as requirement. 在更新主表之前,我们应根据需要在TEMP表上处理数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.