Disable PostgreSQL foreign key checks for migrations

前端 未结 2 1400
攒了一身酷
攒了一身酷 2020-11-29 18:25

I\'m creating a lot of migrations that have foreign keys in PostgreSQL 9.4.

This is creating a headache because the tables must all be in the exact order expected by

相关标签:
2条回答
  • 2020-11-29 18:53

    PostgreSQL doesn't support any configuration option, but there is another possibility.

    postgres=# \d b
            Table "public.b"
    ┌────────┬─────────┬───────────┐
    │ Column │  Type   │ Modifiers │
    ╞════════╪═════════╪═══════════╡
    │ id     │ integer │           │
    └────────┴─────────┴───────────┘
    Foreign-key constraints:
        "b_id_fkey" FOREIGN KEY (id) REFERENCES a(id) DEFERRABLE
    

    The referential integrity in Postgres is implemented by triggers, and you can disable triggers on table. With this method you can upload any data (risk), but it is significantly faster - because the check over large data is expensive. And if your upload is safe, then you can do it.

    BEGIN;
    ALTER TABLE b DISABLE TRIGGER ALL;
    -- now the RI over table b is disabled
    ALTER TABLE b ENABLE TRIGGER ALL;
    COMMIT;
    

    Next possibility is using deferred constraints. This move constraint check to commit time. So you should not to respect order with INSERT commands:

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

    This method should be preferred for you, because the inserted data will be checked.

    0 讨论(0)
  • 2020-11-29 18:56

    For migration, it is easier to disable all triggers with:

    SET session_replication_role = 'replica';
    

    And after migration reenable all with

    SET session_replication_role = 'origin';
    
    0 讨论(0)
提交回复
热议问题