有没有办法将给定 ID 的所有外键引用重新映射到 Postgres 中的另一个 ID?
Is there a way to remap all foreign key references for a given ID to another ID in Postgres?
比方说,有一个 table 带有一个简单的数字 ID 列,其值为 1 和 2。还有几十个其他 table 引用了 ID = 1 的行在他们的外键中。有什么方法可以将所有这些引用级联更新为 2 而无需为所有引用 table 生成更新?
更新以进一步阐明它。
我们得到了这样的字典 table,叫做 CompanyTypes
:
ID | Name
---------
1 | Bar
2 | Restaurant
我们有一堆 table 在他们的 FK 中引用该词典。为简单起见,让我们使用一个名为 Companies
:
ID | Name | Type
----------------------
1 | Cool bar | 1
2 | Not a bar | 2
现在有一个行政决定,我们不再需要酒吧作为一个独特的公司类型,现在所有的酒吧都必须重新映射为餐馆而不改变数据库模式(所以我不能添加映射 table 或类似的东西)。是的,我可以编写一个查询来生成查询以单独更新每个 table(UPDATE Companies SET Type = 2 WHERE Type = 1
等等),但是有什么方法可以欺骗数据库引擎为我做这件事吗?
尝试使用匿名代码块迭代 all tables that have a foreign key related to CompanyTypes
并将 table 名称与 UPDATE
语句连接:
DO $$
DECLARE
row record;
BEGIN
FOR row IN SELECT DISTINCT fk_tco.table_name as fk_table_name
FROM information_schema.referential_constraints rco
JOIN information_schema.table_constraints fk_tco ON
rco.constraint_name = fk_tco.constraint_name AND
rco.constraint_schema = fk_tco.table_schema
JOIN information_schema.table_constraints pk_tco ON
rco.unique_constraint_name = pk_tco.constraint_name AND
rco.unique_constraint_schema = pk_tco.table_schema
WHERE pk_tco.table_name = 'companytypes'
ORDER BY fk_table_name
LOOP
EXECUTE format('UPDATE %s SET Type = 2 WHERE Type = 1',row.fk_table_name);
END LOOP;
END;
$$;
演示:db<>fiddle
比方说,有一个 table 带有一个简单的数字 ID 列,其值为 1 和 2。还有几十个其他 table 引用了 ID = 1 的行在他们的外键中。有什么方法可以将所有这些引用级联更新为 2 而无需为所有引用 table 生成更新?
更新以进一步阐明它。
我们得到了这样的字典 table,叫做 CompanyTypes
:
ID | Name
---------
1 | Bar
2 | Restaurant
我们有一堆 table 在他们的 FK 中引用该词典。为简单起见,让我们使用一个名为 Companies
:
ID | Name | Type
----------------------
1 | Cool bar | 1
2 | Not a bar | 2
现在有一个行政决定,我们不再需要酒吧作为一个独特的公司类型,现在所有的酒吧都必须重新映射为餐馆而不改变数据库模式(所以我不能添加映射 table 或类似的东西)。是的,我可以编写一个查询来生成查询以单独更新每个 table(UPDATE Companies SET Type = 2 WHERE Type = 1
等等),但是有什么方法可以欺骗数据库引擎为我做这件事吗?
尝试使用匿名代码块迭代 all tables that have a foreign key related to CompanyTypes
并将 table 名称与 UPDATE
语句连接:
DO $$
DECLARE
row record;
BEGIN
FOR row IN SELECT DISTINCT fk_tco.table_name as fk_table_name
FROM information_schema.referential_constraints rco
JOIN information_schema.table_constraints fk_tco ON
rco.constraint_name = fk_tco.constraint_name AND
rco.constraint_schema = fk_tco.table_schema
JOIN information_schema.table_constraints pk_tco ON
rco.unique_constraint_name = pk_tco.constraint_name AND
rco.unique_constraint_schema = pk_tco.table_schema
WHERE pk_tco.table_name = 'companytypes'
ORDER BY fk_table_name
LOOP
EXECUTE format('UPDATE %s SET Type = 2 WHERE Type = 1',row.fk_table_name);
END LOOP;
END;
$$;
演示:db<>fiddle