У меня есть таблица, где строки могут быть связаны друг с другом, и логически, отношения между двумя строками (в основном, без направления). (И если вам интересно, да, это действительно должна быть одна таблица. Это две вещи одного и того же логического объекта / типа.) Я могу придумать пару способов представить это:
- Храните отношения и их обратное
- Сохраняйте связь одним способом, ограничивайте базу данных от ее хранения другим способом и имейте два индекса с противоположными порядками для FK (один индекс является индексом PK)
- Сохраните отношения в одном направлении с двумя индексами и позвольте второму быть вставленным так или иначе (звучит немного противно, но эй, полнота)
- Создайте некоторую таблицу группировки и поместите в нее FK на исходной таблице. (Возникает много вопросов. Таблица группировки будет иметь только номер; зачем даже таблица? Сделать FK NULLable или иметь группы с одной связанной строкой?)
Каковы некоторые основные плюсы и минусы этих способов, и, конечно, есть какой-то способ, о котором я не думал?
Вот SQLFiddle для игры: http://sqlfiddle.com/#!12/7ee1a/1/0 . (Получается, что это PostgreSQL, так как это то, что я использую, но я не думаю, что этот вопрос очень специфичен для PostgreSQL.) В настоящее время он хранит как отношение, так и обратное, просто в качестве примера.
database-design
foreign-key
jpmc26
источник
источник
Ответы:
То, что вы разработали, хорошо. Что нужно добавить, так это ограничение, чтобы сделать отношения бесцельными. Таким образом, у вас не может быть
(1,5)
строки без добавления(5,1)
строки.Это может быть выполнено * с помощью самообращающегося ограничения на таблицу мостов.
*: это может быть выполнено в Postgres, Oracle, DB2 и всех СУБД, в которых реализованы ограничения внешнего ключа, как описано в стандарте SQL (отложено, например, проверено в конце транзакции.) Отложенная проверка на самом деле не нужна, так как в SQL- Сервер, который проверяет их в конце оператора и эта конструкция все еще работает. Вы не можете сделать это в MySQL, потому что «InnoDB проверяет ограничения UNIQUE и FOREIGN KEY строка за строкой» .
Итак, в Postgres следующее будет соответствовать вашим требованиям:
Проверено на: SQL-Fiddle
Если вы попытаетесь добавить строку
(1,5)
:Это терпит неудачу с:
Кроме того, вы можете добавить
CHECK
ограничение, если хотите запретить(y,y)
строки:Как вы упомянули, есть и другие способы реализовать это, например, хранить только одно направление отношения (в одной строке, а не в двух) путем принудительного ввода более низкого идентификатора в
x_id1
и более высокого идентификатора вx_id2
столбце. Это выглядит проще для реализации, но обычно приводит к более сложным запросам позже:источник