foundation

Foreign keys

Используйте referential integrity для защиты relationships, понимая cascade behavior и migration constraints.

Foreign key объявляет, что значения дочернего столбца должны существовать в родительской строке (или быть null, если разрешено). БД обеспечивает referential integrity при insert, update и delete — связь не только договорённость в приложении.

					CREATE TABLE order_items (
  id        BIGINT PRIMARY KEY,
  order_id  BIGINT NOT NULL REFERENCES orders(id) ON DELETE RESTRICT,
  product_id BIGINT NOT NULL REFERENCES products(id)
);
				

| `ON DELETE` / `ON UPDATE` | Эффект | |-----------------------------|--------| | `RESTRICT` / `NO ACTION` | Блокирует изменение родителя при наличии детей | | `CASCADE` | Распространяет delete/update на дочерние строки | | `SET NULL` | Обнуляет FK при удалении родителя |

`CASCADE` упрощает очистку, но может неожиданно снести глубокое дерево и долго держать locks. `RESTRICT` выявляет риск «осиротевших» строк в момент delete. Массовые загрузки и blue/green-миграции иногда временно снимают FK — зафиксируйте окно и перепроверьте целостность после.

На интервью: объясните, зачем FK в схеме для денег и складского учёта, и когда команды откладывают их (шардированные записи, legacy ETL) с компенсирующими проверками.

Типовые ошибки: нет индекса на FK-столбцах (медленные join и проверки locks); цепочки `CASCADE`, удаляющие больше задуманного; целостность только в приложении, проигрывающая гонкам; добавление FK к «грязной» таблице без backfill-аудита.

Компромисс — между корректностью, навязанной БД, и гибкостью миграций / cross-shard ссылок: используйте FK там, где битая связь — инцидент в production, а не повод для логирования.

Чеклист:

  • Назовите родительскую и дочернюю таблицы и кардинальность.
  • Явно выберите поведение `ON DELETE`.
  • Индексируйте каждый FK-столбец в join.
  • Опишите migration/backfill до включения constraint.
  • Сформулируйте, что ломается при целостности только в приложении.