Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable PostgreSQL foreign key checks for migrations

Tags:

postgresql

People also ask

How do I disable foreign key check in SQL?

You can disable foreign key check in MySQL by setting the system variable foreign_key_checks to 0. However, please note, after you enable foreign key checks, MySQL will not re-validate your existing data that you added after disabling foreign key check. It will only check any new additions/updates to your database.

Can we disable foreign key constraint?

You can disable a foreign key constraint during INSERT and UPDATE transactions in SQL Server by using SQL Server Management Studio or Transact-SQL. Use this option if you know that new data will not violate the existing constraint or if the constraint applies only to the data already in the database.

Do I need to index foreign keys Postgres?

In contrast to the above, PostgreSQL requires no index at the source of a foreign key. However, such an index is quite useful for finding all source rows that reference a target row.


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';

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.