简体   繁体   English

如何在Postgres中基于INSERT RETURNING id进行SQL更新?

[英]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: 这种方法有一些好处:

  • Taking advantage of RETURNING as you asked, but in update step. 根据您的要求利用RETURNING的优势,但要进行update Avoiding an unnecessary extra SELECT; 避免不必要的额外SELECT;
  • Concurrency safe; 并发安全;
  • Postponing FK creation will result in a faster script; 推迟FK的创建将使脚本速度更快;
  • Using pure SQL solution, no need to use procedural language; 使用纯SQL解决方案,无需使用过程语言;
  • Avoiding read and write to old_table at same step. 避免在同一步骤中读写old_table。

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.

相关问题 如何根据计数进行更新 - SQL(postgres) - How to do an update based on a count - SQL (postgres) SQL(postgres)在INSERT INTO / UPDATE之后从多个表中返回数据 - SQL (postgres) RETURNING data from multiple tables after an INSERT INTO / UPDATE 如何根据返回相同数据的多列进行更新或插入,而无需访问唯一 ID - How to UPDATE or INSERT based on multiple columns returning the same data, without having access to the unique ID 根据 SELECT 有条件地执行 INSERT 导致 postgres sql function - Conditionally do INSERT based on SELECT result in postgres sql function SQL IF NOT EXISTS INSERT Else Update,基于列ID - SQL IF NOT EXISTS INSERT Else Update, based on column ID 如何在postgres INSERT ON CONFLICT DO UPDATE中返回列的旧值? - How to return the old value of a column in a postgres INSERT ON CONFLICT DO UPDATE? 如何在 Postgres 中使用 ON CONFLICT UPDATE 子句插入多条记录? - How do I insert multiple records with an ON CONFLICT UPDATE clause in Postgres? 如何根据以前的 ID 在 Postgres 中找到下一行? - How do I find next row in Postgres based on previous Id? 如何更正我的 Postgres sql 插入语句? - How do i correct my Postgres sql insert statement? 如何使用 Prisma 在行数条件下为 Postgres 插入 SQL? - How to do SQL insert for Postgres using Prisma with condition on count of rows?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM