2016-06-30 74 views
9

我在PostgreSQL 9.4中創建了大量具有外鍵的遷移。禁用PostgreSQL外鍵檢查遷移

這是創建一個令人頭疼的問題,因爲這些表在遷移時必須完全按照外鍵預期的順序排列。如果我必須從其他軟件包運行我的新遷移依賴於外鍵的遷移,它會變得更加棘手。

在MySQL中,我可以通過簡單地將SET FOREIGN_KEY_CHECKS = 0;添加到我的遷移文件的頂部來簡化此操作。我如何才能在PostgresSQL中僅爲遷移代碼的長度臨時執行此操作?

順便說一句,使用Laravel架構生成器爲此。

回答

18

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

這種方法應該是首選的你,因爲插入的數據將被檢查。