Какие виды связей существуют в PostgreSQL
Что проверяют
Понимаете ли вы, как связи между сущностями реализуются в самой базе и как это отражается в EF Core. Следом часто спрашивают, что будет с дочерними строками при удалении родителя и нужен ли индекс на внешний ключ.
Как отвечать
Видов связей по кардинальности три, и все они строятся на FOREIGN KEY:
- один ко многим: в дочерней таблице колонка со ссылкой на ключ родителя, например
orders.customer_id. Самый частый вариант; - один к одному: тот же внешний ключ плюс
UNIQUEна нём либо общий первичный ключ, когдаprofiles.user_idодновременно PK и FK. Так выносят редкие или чувствительные поля в отдельную таблицу; - многие ко многим: промежуточная таблица с двумя внешними ключами и составным первичным ключом
(student_id, course_id).
Иерархии (сотрудник и руководитель, дерево категорий) не отдельный вид, а связь один ко многим таблицы на саму себя. Обходят их через WITH RECURSIVE или расширение ltree.
У внешнего ключа есть поведение при удалении и изменении: NO ACTION по умолчанию, RESTRICT, CASCADE, SET NULL, SET DEFAULT. Важная деталь PostgreSQL: индекс на ссылающуюся колонку он сам не создаёт. Индекс есть только у той стороны, на которую ссылаются, она обязана быть PK или UNIQUE.
В EF Core с провайдером Npgsql связь описывают через HasOne(...).WithMany(...).HasForeignKey(...), а многие ко многим с EF Core 5 задаются навигациями с обеих сторон, промежуточную таблицу фреймворк создаст сам. Для обязательной связи EF по умолчанию ставит каскадное удаление, а индексы на внешние ключи миграции добавляют по соглашению.
Если интервьюер под «связями» имел в виду соединения, перечислите INNER, LEFT, RIGHT, FULL и CROSS JOIN.
Где спотыкаются
Забывают индекс на внешнем ключе в ручных миграциях. Удаление родителя и JOIN превращаются в полный просмотр дочерней таблицы.
Делают один к одному без UNIQUE, и база спокойно принимает второй профиль для того же пользователя.
Оставляют CASCADE везде, и одно удаление клиента стирает заказы, платежи и историю.