Вимкніть перевірку зовнішнього ключа PostgreSQL на міграцію


93

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

Це створює головний біль, тому що всі таблиці повинні бути в точному порядку, як очікується від зовнішніх ключів при їх міграції. Це стає ще більш важким, якщо мені доводиться запускати міграції з інших пакетів, від яких залежать мої нові міграції для зовнішнього ключа.

У MySQL я можу спростити це, просто додавши SET FOREIGN_KEY_CHECKS = 0;у верхню частину мого файлу міграції. Як я можу тимчасово зробити це в PostgresSQL лише на довжину коду міграції?

До речі, використовуючи для цього конструктор схем Laravel.

Відповіді:


84

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
З якоїсь причини це один раз спрацювало для мене, а потім зовсім не. Я перебуваю в aws aurora postgres, де вони блокують super userроль, щоб клієнти не могли зіпсувати налаштування реплікації. Схоже, я повинен бути суперкористувачем, щоб відключити деякі системні тригери. (Зараз я використовую свій обліковий запис адміністратора, який також є власником - я не впевнений, чому це спрацювало одного разу.) Встановлення параметра реплікації також не є життєздатним варіантом, оскільки для цього також потрібна super userроль. Здається, мій єдиний варіант - скинути та відтворити зовнішні ключі ...
ps2goat

Те ж саме. Робити DISABLE TRIGGER ALLщось, але це не має ефекту. Я навіть не отримую жодного попередження. Це просто ігнорується.
jayarjo

На Amazon RDS це видає таку помилку:> відмовлено в дозволі: "RI_ConstraintTrigger_a_23031" є системним тригером, тому цей рецепт, на жаль, не для кожного випадку :)
kolypto

Помилка на локальному базі даних також. Оскільки користувач має всі привілеї до бази даних, отримано ** відмову у дозволі: "RI_ConstraintTrigger_a_16564" є системним тригером **
Solo.dmitry

155

Для міграції простіше вимкнути всі тригери за допомогою:

SET session_replication_role = 'replica';

А після міграції відновити всі з

SET session_replication_role = 'origin';

3
Свята корово, чи це одночасно і простіше, і більш доречно для конкретного завдання, що порушується. (Так.)
ijoseph

10
Слово обережності: для цього потрібні привілеї суперкористувача. Спробуйте "ВСТАНОВИТИ ОБМЕЖЕННЯ ВСІХ ВІДСТАНОВЛЕНИХ".
JJC

9
Я працюю, 10.4і це вище твердження, здається, не працює.
Стефан

2
Чи зможе хтось окреслити небезпеки / ризики цього методу та в яких сценаріях його слід використовувати та як пом'якшити ризики? Що є найкращою практикою, якщо це вважається поганою практикою?
karns

6
До речі, цей параметр можна встановити в AWS RDS у групі параметрів бази даних і застосувати без перезапуску db! Дуже корисно, якщо ви використовуєте DMS у порожній базі даних зі створеною схемою та обмеженнями.
Майк Атлас,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.