(TL;DR位于末尾)
我正在合并两个大小合适的postgres数据库。由于存在ID冲突和许多外键,我希望UPDATE foo SET bar_id = bar_id + 100000 CASCADE
是SQL中的一个东西,所以它会神奇地相应地更新所有内容。不幸的是,它不是。
所以我想使用一个LOOP结构(见下文),它可以简单地编辑所有引用。我想使用一个选择查询,返回所有引用了我想要的列的table_name,column_name。
DO
$$
DECLARE
rec record;
BEGIN
FOR rec IN
(SELECT table_name, column_name FROM /*??*/ WHERE /*??*/) -- <<< This line
LOOP
EXECUTE format('UPDATE %I SET %s = %s + 100000 ;',
rec.table_name,rec.column_name,rec.column_name);
END LOOP;
END;
$$
LANGUAGE plpgsql;
我已经知道如何获取所有具有特定column_name的表(+column_name),当外键列与其引用的列共享该名称时,我将使用该名称。
SELECT col.table_name, col.column_name
FROM information_schema.columns col
right join
information_schema.tables tab
ON col.table_name = tab.table_name
WHERE column_name = 'foo_id'
-- IN ('FOO_ID','BAR_FOO_ID') | or : like '%foo_id' | both works well most of the time
and tab.table_type = 'BASE TABLE'
但是......我现在有一个PLACES表,其中place_id
列被至少60个不同的约束引用(匹配LIKE '%place_id'
)。* 然后存在引用以其它方式命名的地点id的列 *,例如“foo_currentplace”、"foo_storageroom“、”foo_lastrecomposition_place“、”operating_theatre“等等。有列从位置类型表中引用“位置类型_id”,这些列是LIKE '%place%'
,我不想更改位置类型_id,因此我们无法仅从名称中猜测要包括或不包括哪一列。
我知道有information_schema.table_constraints
表,但它没有告诉引用的列。如果我们可以从约束名称中获得定义,则可能匹配:ILIKE format('%%REFERENCES %s(%s)%%',table_name,column_name)
但是这个定义也不是table_constraints
表的一部分。
(For那些想知道的人,我正在研究与消毒服务相关的医院数据库。)
我想要什么/ TL;德国
我需要一个SELECT查询(或函数定义)返回整个数据库(schema_name,table_name,column_name)
或(table_name,column_name)
的所有列,这些列具有引用指定列(参数)的外键约束。
2条答案
按热度按时间5n0oy7gb1#
好吧,所以我已经做到了:-)
以下查询返回数据库中引用
FOO_TABLE.foo_column
作为外键的每一列:Test it there
我发现
information_schema.table_constraints
从pg_constraint
获得大部分信息,其中包括内部引用OID
,并且有一个内置函数pg_get_constraintdef()
从它的OID
返回约束对象的定义。然后,定义的某个子字符串就足以使用我在问题中准备的
(I)LIKE
过滤器在引用列上提取column_name
AND过滤器。我通过改进@Abelisto建议构建的另一个可接受的查询:
Test it there
我不认为性能在这里真的很重要,所以应该考虑哪些是次要的需求。我认为我的第一个解决方案的优点是,如果您想更改约束定义(例如,添加一个
ON UPDATE CASCADE
子句),那么第二个解决方案似乎更“紧凑”,因为它只返回table. column。yizd12fk2#
这也许太长了,不宜评论。
Postgres绝对支持级联更新约束(见这里),但是这是约束的 * 定义 * 的一部分,而不是
update
语句:注意:您需要重新定义所有外键约束,使它们成为级联更新约束。
而且,作为一个编辑评论,我通常避免级联更新外键约束(因为我不喜欢主键更改值的想法),然而,这绝对是它们有用的地方。
然后,如果您更改
bar.bar_id
,更改将反映在foo
中。Here是db〈〉小提琴。