我想将数据从几个类似结构的表(如
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
参见示例
测试数据模型:
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 | 空 |