Отключить внешний ключ PostgreSQL для миграции

Я создаю много миграций с внешними ключами в PostgreSQL 9.4.

Это создает головную боль, потому что все таблицы должны быть в точном порядке, ожидаемом внешними ключами при их переносе. Он становится еще более стильным, если мне нужно выполнить миграцию из других пакетов, на которые зависят мои новые миграции для внешнего ключа.

В MySQL я могу упростить это, просто добавив SET FOREIGN_KEY_CHECKS = 0; в начало моего файла миграции. Как я могу сделать это временно в PostgresSQL только для длины кода миграции?

Кстати, используя Laravel Schema Builder для этого.

Ответ 1

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

Этот метод должен быть вам предпочтительным, потому что вставленные данные будут проверены.

Ответ 2

Для миграции легче отключить все триггеры с помощью:

SET session_replication_role = 'replica';

И после перенастройки все с

SET session_replication_role = 'origin';