我在PostgreSQL 9.4中创建了大量具有外键的迁移。
这令人头疼,因为这些表在迁移时必须完全符合外键所需的确切顺序。如果我必须从我的新迁移所依赖的其他包中运行迁移,那么它会变得更加棘手。
在MySQL中,我可以通过简单地将SET FOREIGN_KEY_CHECKS = 0;
添加到我的迁移文件的顶部来简化这一过程。如何只在迁移代码的长度内在PostgresSQL中暂时执行此操作?
BTW,使用Laravel Schema Builder进行此操作。
答案 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".
此方法应该是首选,因为将检查插入的数据。