我正在创建很多迁移,这些迁移在PostgreSQL 9.4中具有外键。
令人头疼的是,表在迁移时必须全部按照外键期望的准确顺序排列。如果我必须从我的新迁移所依赖的其他程序包运行迁移来获得外键,则会变得更加棘手。
在MySQL中,只需将其添加SET FOREIGN_KEY_CHECKS = 0;
到迁移文件的顶部即可简化此过程。如何仅在迁移代码的长度内临时在PostgresSQL中执行此操作?
顺便说一句,为此使用Laravel Schema Builder。
Answers:
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".
您应该首选此方法,因为将检查插入的数据。
DISABLE TRIGGER ALL
,但没有效果。我什至没有得到任何警告。它只是被忽略。
对于迁移,使用以下命令更容易禁用所有触发器:
SET session_replication_role = 'replica';
迁移后重新启用所有
SET session_replication_role = 'origin';
10.4
正在进行,上面的声明似乎不起作用。
super user
角色,这样客户就不会弄乱复制设置。看来我必须是超级用户才能禁用某些系统触发器。(我目前使用的管理员帐户也是所有者,我不确定为什么它一次可以使用。)设置复制选项也不是一个可行的选择,因为这也需要super user
角色。我唯一的选择似乎是删除并重新创建外键...