禁用PostgreSQL外键检查迁移

时间:2016-06-30 01:03:56

标签: postgresql

我在PostgreSQL 9.4中创建了大量具有外键的迁移。

这令人头疼,因为这些表在迁移时必须完全符合外键所需的确切顺序。如果我必须从我的新迁移所依赖的其他包中运行迁移,那么它会变得更加棘手。

在MySQL中,我可以通过简单地将SET FOREIGN_KEY_CHECKS = 0;添加到我的迁移文件的顶部来简化这一过程。如何只在迁移代码的长度内在PostgresSQL中暂时执行此操作?

BTW,使用Laravel Schema Builder进行此操作。

2 个答案:

答案 0 :(得分:55)

对于迁移,使用以下命令禁用所有触发器更容易:

SET session_replication_role = 'replica';

迁移后重新启用所有

SET session_replication_role = 'origin';

答案 1 :(得分:43)

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".

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