将 SQL 数据从一个表移动到另一个表,并在第三个表中保留外键

问题描述 投票:0回答:1

我想将数据从几个类似结构的表(如

old_metadata
)移动到表
new_metadata
,并分别更新表中的引用。例如,
deposit
具有引用
metadata_id
的字段
old_metadata.id
。诀窍是,在创建
new_metadata
表中的记录 id 之前,我不知道它们; 表结构如下:

old_metadata

id | amount
---+-------
0  | 30
1  | 40
new_metadata

id | amount | metadata_type
---+--------+--------------
31 | 30     | OLD_METADATA
32 | 40     | OLD_METADATA
deposits

id | metadata_id | ...
---+-------------+----
11 | 1           |
12 | 2           |

所以我尝试过的是

ALTER TABLE deposits ADD COLUMN new_metadata_id INT REFERENCES new_metadata(id);

WITH metadata AS (
    INSERT INTO new_metadata (amount, metadata_type)
        SELECT amount, 'OLD_METADATA' FROM old_metadata
        RETURNING id, old_metadata.id as old_id
) 
UPDATE deposits SET new_metadata_id = metadata.id
FROM metada
WHERE metadata_id = metadata.old_id;

我的下一步是将旧列中的数据替换为新列中的数据,但它失败了,说

missing FROM-clause entry for table "old_metadata"
。 或者,也可以使用游标或临时表来完成,但我相信这不是最直接的方法。

草率但可行的解决方案就像这样

ALTER TABLE new_metadata ADD COLUMN old_id INT;
ALTER TABLE deposits ADD COLUMN new_metadata_id INT;

WITH metadata AS (
    INSERT INTO new_metadata (amount, metadata_type, old_id)
        SELECT amount, 'OLD_METADATA', id FROM old_metadata
        RETURNING *
)
UPDATE deposits SET new_metadata_id = metadata.id
FROM new_metadata, old_metadata
WHERE metadata_id = new_metadata.old_id;

UPDATE deposits SET metadata_id = deposits.new_metadata_id

ALTER TABLE deposits DROP COLUMN new_metadata_id
ALTER TABLE new_metadata DROP COLUMN old_id
postgresql
1个回答
0
投票

参见示例

测试数据模型:

create table old_metadata ( id int primary key generated by default as identity, amount int);
insert into old_metadata values
 (0, 30)
,(1, 40)
,(2, 50)
;
create table new_metadata ( id int primary key generated by default as identity
  , amount int,metadata_type varchar(20));
insert into new_metadata values
 (31 , 30,    'OLD_METADATA')
,(32 , 40,    'OLD_METADATA')
;
create table deposits ( id int primary key generated by default as identity
  , metadata_id int );
alter table deposits add constraint 
    cx_reference_fk_old_metadata FOREIGN KEY (metadata_id) references old_metadata;
insert into deposits values
 (11 , 1)
,(12 , 2)
;

创建表,插入 0 3,创建表,插入 0 2,创建表,更改表,插入 0 2

旧元数据

id 金额
0 30
1 40
2 50

新元数据

id 金额 元数据类型
31 30 旧元数据
32 40 旧元数据

存款

id 元数据_id
11 1
12 2
ALTER TABLE new_metadata ADD COLUMN old_metadata_id INT REFERENCES old_metadata(id);
SELECT setval('new_metadata_id_seq', max(id)) FROM new_metadata;
设定值
32
ALTER TABLE deposits DROP CONSTRAINT cx_reference_fk_old_metadata;
WITH metadata AS (
    INSERT INTO new_metadata (amount, metadata_type,old_metadata_id)
        SELECT amount, 'OLD_METADATA' metadata_type,id as old_metadata_id FROM old_metadata
        RETURNING id, old_metadata_id 
) 
UPDATE deposits SET metadata_id = metadata.id
FROM metadata
WHERE metadata_id = old_metadata_id;
UPDATE 2
alter table deposits add constraint 
    cx_reference_fk_new_metadata FOREIGN KEY (metadata_id) references new_metadata;
ALTER TABLE
select * from old_metadata;
select * from new_metadata;
select * from deposits;

旧元数据

id 金额
0 30
1 40
2 50

新元数据

id 金额 元数据类型 old_metadata_id
31 30 旧元数据
32 40 旧元数据
33 30 旧元数据 0
34 40 旧元数据 1
35 50 旧元数据 2

存款

id 元数据_id
11 34
12 35

小提琴

SELECT * FROM pg_sequences WHERE sequencename LIKE '%id%';
架构名称 序列名称 序列所有者 数据类型 起始值 最小值 最大值 增量_by 循环 缓存大小 最后一个值
公开 old_metadata_id_seq postgres 整数 1 1 2147483647 1 f 1
公开 new_metadata_id_seq postgres 整数 1 1 2147483647 1 f 1 35
公开 存款_id_seq postgres 整数 1 1 2147483647 1 f 1
© www.soinside.com 2019 - 2024. All rights reserved.