Pio*_*sen 14 postgresql foreign-key amazon-rds
我正在将现有测试环境迁移到 Amazon RDS PostgreSQL。测试框架具有将某些表中的数据重新加载到早期状态的功能。为此,它禁用外键、删除现有数据、加载保存状态并再次启用外键。
目前,测试框架通过禁用所有触发器来禁用外键(当然,这需要超级用户):
alter table tablename disable trigger all;
Run Code Online (Sandbox Code Playgroud)
在 RDS 上,这失败了:
错误:权限被拒绝:“RI_ConstraintTrigger_a_20164”是系统触发器
如何在 Amazon RDS PostgreSQL 中临时禁用外键?
注意:已经提出了类似的问题(RDS 上的 PostgreSQL:如何使用 FK 约束批量导入数据?)但它专门针对离线导入,并且该解决方案也特定于离线导入。
Pio*_*sen 18
我找到了一种禁用外键的替代方法——https: //stackoverflow.com/a/18709987
set session_replication_role = replica;
Run Code Online (Sandbox Code Playgroud)
并重新启用它们
set session_replication_role = default;
Run Code Online (Sandbox Code Playgroud)
这适用于 RDS,但仍需要特殊权限(即默认情况下未授予)。
正如评论中所建议的,替代解决方案是暂时删除 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 $$;
Run Code Online (Sandbox Code Playgroud)
再创造
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 $$;
Run Code Online (Sandbox Code Playgroud)