Можно ли сделать select с join по id без внешнего ключа?
Что проверяют
Понимаете ли вы, что внешний ключ это ограничение целостности, а не условие соединения таблиц. Следом обычно спрашивают, как связать такие сущности в JPA и что будет со строками, которые ссылаются в никуда.
Как отвечать
Да, можно. JOIN ... ON принимает любое логическое условие: равенство по id, диапазон, выражение. Запрос SELECT u.name, o.id FROM users u JOIN orders o ON o.user_id = u.id работает одинаково, объявлен FOREIGN KEY или нет.
Что даёт внешний ключ и чего вы лишаетесь без него:
- целостность: база не даст вставить заказ с несуществующим
user_idи удалить пользователя, у которого есть заказы, либо удалит их поON DELETE CASCADE; - сироты: без FK появляются записи со ссылкой в никуда.
INNER JOINмолча их отбрасывает,LEFT JOINпоказываетNULL, и отчёты начинают расходиться; - индекс: в PostgreSQL FK не создаёт индекс на ссылающуюся колонку, в MySQL InnoDB создаёт. Для быстрого соединения индекс на
orders.user_idнужен в любом случае.
Без FK живут сознательно: таблицы в разных базах или сервисах, журналы с интенсивной записью, данные после миграции из старой системы.
Что это значит в Java:
- связь без ограничения в схеме:
@ManyToOneс@JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)), и Hibernate не создаст FK при генерации DDL; - соединение несвязанных сущностей: HQL начиная с Hibernate 5.1 понимает
join Order o on o.userId = u.idбез объявленной связи; - явный SQL: нативный запрос,
JdbcTemplateили jOOQ, где условие соединения пишется руками.
Где спотыкаются
Думают, что FK ускоряет соединение. Скорость даёт индекс, а в PostgreSQL его на ссылающуюся колонку создают отдельно.
Соединяют колонки разных типов, например bigint с varchar. MySQL молча приводит типы на каждой строке и перестаёт использовать индекс, PostgreSQL сразу выдаёт ошибку об отсутствии оператора.
Не говорят о сиротах. Без FK целостность обеспечивают кодом и регулярными проверками вроде LEFT JOIN ... WHERE u.id IS NULL, иначе расхождения первыми найдут пользователи.