禁用迁移的PostgreSQL外键检查

禁用迁移的PostgreSQL外键检查,postgresql,Postgresql,我在PostgreSQL 9.4中创建了许多具有外键的迁移 这是一个令人头痛的问题,因为表在迁移时必须完全按照外键所期望的顺序。如果我必须从我的新迁移所依赖的外键的其他包中运行迁移,那么它会变得更加棘手 在MySQL中,我可以通过简单地添加SET-FOREIGN\u-KEY\u-CHECKS=0来简化这一点到我的迁移文件的顶部。如何在PostgresSQL中仅针对迁移代码的长度临时执行此操作 顺便说一句,使用Laravel Schema Builder进行此操作。PostgreSQL不支持任何配

我在PostgreSQL 9.4中创建了许多具有外键的迁移

这是一个令人头痛的问题,因为表在迁移时必须完全按照外键所期望的顺序。如果我必须从我的新迁移所依赖的外键的其他包中运行迁移,那么它会变得更加棘手

在MySQL中,我可以通过简单地添加
SET-FOREIGN\u-KEY\u-CHECKS=0来简化这一点到我的迁移文件的顶部。如何在PostgresSQL中仅针对迁移代码的长度临时执行此操作


顺便说一句,使用Laravel Schema Builder进行此操作。

PostgreSQL不支持任何配置选项,但还有另一种可能性

postgres=# \d b
        Table "public.b"
┌────────┬─────────┬───────────┐
│ Column │  Type   │ Modifiers │
╞════════╪═════════╪═══════════╡
│ id     │ integer │           │
└────────┴─────────┴───────────┘
Foreign-key constraints:
    "b_id_fkey" FOREIGN KEY (id) REFERENCES a(id) DEFERRABLE
Postgres中的引用完整性是由触发器实现的,您可以在表上禁用触发器。使用这种方法,您可以上传任何数据(风险),但速度要快得多,因为对大数据的检查非常昂贵。如果你的上传是安全的,那么你可以这样做

BEGIN;
ALTER TABLE b DISABLE TRIGGER ALL;
-- now the RI over table b is disabled
ALTER TABLE b ENABLE TRIGGER ALL;
COMMIT;
下一种可能性是使用延迟约束。此移动约束检查用于提交时间。因此,您不应使用
INSERT
命令遵守顺序:

ALTER TABLE b ALTER CONSTRAINT b_id_fkey DEFERRABLE;

BEGIN
postgres=# SET CONSTRAINTS b_id_fkey DEFERRED;
SET CONSTRAINTS
postgres=# INSERT INTO b VALUES(100); -- this is not in a table
INSERT 0 1
postgres=# INSERT INTO b VALUES(10);
INSERT 0 1 
postgres=# COMMIT;
ERROR:  insert or update on table "b" violates foreign key constraint "b_id_fkey"
DETAIL:  Key (id)=(100) is not present in table "a".

您应该首选此方法,因为将检查插入的数据

对于迁移,禁用所有触发器更容易:

SET session_replication_role = 'replica';
迁移后,可重新启用所有

SET session_replication_role = 'origin';

天哪,这是不是更简单,更适合手头的具体任务。(是。)警告:这需要超级用户权限。尝试“设置所有延迟的约束条件”。我使用的是
10.4
,上面的陈述似乎不起作用。有人能概述这种方法的危险/风险,在什么情况下应该使用它,以及如何降低风险吗?如果这被认为是一个糟糕的做法,那么最佳做法是什么?顺便说一句,这个参数可以在数据库参数组中的AWS RDS中设置并应用,而无需重新启动数据库!如果将DMS用于创建了现有模式和约束的空数据库中,这非常有用。出于某种原因,这对我来说只起过一次作用,然后就完全没有了。我在aws aurora postgres,在那里他们锁定了超级用户角色,这样客户就不会弄乱复制设置。看起来我必须是超级用户才能禁用一些系统触发器。(我目前使用的是我的管理员帐户,该帐户也是所有者——我不知道为什么它会工作一次。)设置复制选项也是不可行的,因为这还需要
超级用户
角色。我唯一的选择似乎是删除并重新创建外键…这里也是。执行
禁用触发所有
操作,但没有效果。我甚至没有收到任何警告。它只是被忽略了。在Amazon RDS上,这会产生以下错误:>权限被拒绝:“RI_ConstraintTrigger_a_23031”是一个系统触发器,因此此配方并不适用于所有情况,不幸的是:)本地数据库上也有错误。由于用户拥有对数据库的所有权限,因此**权限被拒绝:“RI_ConstraintTrigger_a_16564”是一个系统触发器**@otocan-不,还没有。表演是一样的。理论上,它可以以不同的方式实现,但没有人做过这项工作。