生成禁用许多表中的外键的脚本

时间:2019-01-18 22:18:05

标签: postgresql foreign-keys

我正在制作一个刷新脚本,我们在

  1. DROP表约束,
  2. TRUNCATE表格
  3. 表和中的
  4. INSERT数据
  5. ADD在第一步中删除的约束。

我使用动态SQL创建了以下SQL,以控制SQL DROP外键约束,以便我可以针对正在处理的多个表执行

SELECT 
'ALTER TABLE  SSP2_PCAT.' || TABLE_NAME || ' DROP CONSTRAINT ' || CONSTRAINT_NAME || ';' 
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE 
UPPER(CONSTRAINT_SCHEMA) = 'SSP2_PCAT' AND
UPPER(TABLE_NAME) IN (RATES,.....);

以上SQL的输出将如下所示,

ALTER TABLE SSP2_PCAT.RATES DROP CONSTRAINT fk_rate;

截断上面提到的方法非常简单。

通过启用DBlink将WITH子句与STRING_AGG函数一起使用 POSTGRES中的扩展类似地使用动态SQL,以便一次性提供多个表的SQL。

现在我正在研究类似的查询,以添加如下约束(第一步已删除)

SELECT DISTINCT 'ALTER TABLE  ' || cs.TABLE_NAME || 
' ADD CONSTRAINT ' ||rc.CONSTRAINT_NAME ||
' FOREIGN KEY ' ||c.COLUMN_NAME ||
' REFERENCES ' ||cs.TABLE_NAME || ' (' || cs.CONSTRAINT_NAME || ') ' || ' ON UPDATE ' || rc.UPDATE_RULE || ' ON DELETE ' || rc.DELETE_RULE
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC, INFORMATION_SCHEMA.TABLE_CONSTRAINTS CS, INFORMATION_SCHEMA.COLUMNS C
WHERE cs.CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND
cs.TABLE_NAME = c.TABLE_NAME AND
UPPER(cs.TABLE_NAME) = 'ADDITIONAL_RULES' AND
UPPER(cs.TABLE_SCHEMA) = 'SSP2_PCAT';

但是不幸的是,该查询未提供期望的结果,似乎我缺少了某些东西,尤其是在选择c.COLUMN_NAME字段而不是引用字段时,它提供了表中的所有可用字段,也是没有给出Parent_table cs.TABLE_NAME的名称,而是给出了相同的table_name。如果我从任何其他数据字典表中丢失任何联接,可以有人让我发布吗?

1 个答案:

答案 0 :(得分:1)

您不需要删除并重新创建外键。请改用延迟约束。将外键定义为deferrable initially deferred并在单个事务中执行所有插入就足够了。但是,还有更多选项,因此请阅读文档中有关可延迟约束的信息:


使用系统目录pg_constraint.

您可以通过以下方式生成脚本以将外键更改为DEFERRABLE INITIALLY DEFERRED

select format(
    'ALTER TABLE %s ALTER CONSTRAINT %s DEFERRABLE INITIALLY DEFERRED;', 
    conrelid::regclass::text, 
    conname)
from pg_constraint
where contype = 'f' 
and conrelid = any(array['table1', 'table2', 'table3']::regclass[])
and connamespace = 'ssp2_pcat'::regnamespace;

您可以运行一次脚本。然后,您的导入脚本可能如下所示:

BEGIN;
TRUNCATE table1;
TRUNCATE table2;
...
INSERT INTO table1...
INSERT INTO table2...
...
COMMIT;

如果由于某种原因您不能使用延迟约束,请使用脚本删除约束:

select
    format(
        'ALTER TABLE %s DROP CONSTRAINT %s;', 
        conrelid::regclass::text, 
        conname)
from pg_constraint
where contype = 'f' 
and conrelid = any(array['table1', 'table2', 'table3']::regclass[])
and connamespace = 'ssp2_pcat'::regnamespace;

并重新创建它们:

select
    format(
        'ALTER TABLE %s ADD CONSTRAINT %s %s;', 
        conrelid::regclass::text, 
        conname, 
        pg_get_constraintdef(oid))
from pg_constraint
where contype = 'f' 
and conrelid = any(array['table1', 'table2', 'table3']::regclass[])
and connamespace = 'ssp2_pcat'::regnamespace;