如何在Amazon RDS PostgreSQL中临时禁用外键?


10

我正在将现有测试环境迁移到Amazon RDS PostgreSQL。测试框架具有将某些表中的数据重新加载到较早状态的功能。为此,它将禁用外键,删除现有数据,加载保存状态并再次启用外键。

当前,测试框架通过禁用所有触发器来禁用外键(当然,这需要超级用户):

alter table tablename disable trigger all;

在RDS上,此操作失败并显示:

错误:权限被拒绝:“ RI_ConstraintTrigger_a_20164”是系统触发器

如何在Amazon RDS PostgreSQL中临时禁用外键?

注意:已经问过类似的问题(RDS上的PostgreSQL:如何在FK约束下批量导入数据?),但这是专门针对脱机导入的,解决方案也针对脱机导入。


也许这应该是一个stackoverflow问题?
Piotr Findeisen

不同意-这与数据库管理非常相关。
Vérace

您现在如何禁用FK?您为什么期望它在RDS上有所不同?另外,为什么不尝试一下呢?
dezso 2015年

@dezso,感谢您的评论。当然,我添加了在非RDS PostgreSQL上使用的代码。
Piotr

哦,是的,这样就行不通了。但是,如何删除并重新创建FK约束呢?
dezso

Answers:


11

session_replication_role

我发现了禁用外键的另一种方法-https: //stackoverflow.com/a/18709987

set session_replication_role = replica;

并重新启用它们

set session_replication_role = default;

这在RDS上有效,但仍需要异常特权(即默认情况下未授予)。

删除并重新创建FK

如评论中所建议,替代解决方案是暂时删除FK。这带来了额外的优势,即在重新启用FK时可以验证数据。

掉落

create table if not exists dropped_foreign_keys (
        seq bigserial primary key,
        sql text
);

do $$ declare t record;
begin
    for t in select conrelid::regclass::varchar table_name, conname constraint_name,
            pg_catalog.pg_get_constraintdef(r.oid, true) constraint_definition
            from pg_catalog.pg_constraint r
            where r.contype = 'f'
            -- current schema only:
            and r.connamespace = (select n.oid from pg_namespace n where n.nspname = current_schema())
        loop

        insert into dropped_foreign_keys (sql) values (
            format('alter table %s add constraint %s %s',
                quote_ident(t.table_name), quote_ident(t.constraint_name), t.constraint_definition));

        execute format('alter table %s drop constraint %s', quote_ident(t.table_name), quote_ident(t.constraint_name));

    end loop;
end $$;

重新建立

do $$ declare t record;
begin
    -- order by seq for easier troubleshooting when data does not satisfy FKs
    for t in select * from dropped_foreign_keys order by seq loop
        execute t.sql;
        delete from dropped_foreign_keys where seq = t.seq;
    end loop;
end $$;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.