Как правильно моделировать данные в базах данных на основе SQL, которые имеют некоторые общие столбцы, но также имеют уникальные столбцы? - PullRequest
3 голосов
/ 02 апреля 2010

Например, допустим, у меня есть модель пользователя. У пользователей есть такие вещи, как логины, пароли, адреса электронной почты, аватары и т. Д. Но есть два типа пользователей, которые будут использовать этот сайт, скажем, родители и бизнес. Мне нужно хранить некоторую другую информацию для родителей (например, имена детей, домашний партнер, зарплаты и т. Д.), Чем для предприятий (например, промышленность, количество сотрудников и т. Д.), Но также некоторые из них такие же, как логины и пароли.

Как правильно структурировать это в базе данных на основе SQL? Спасибо!

- ОБНОВЛЕНИЕ -

После того, как я покопался немного больше, я думаю, что полиморфная ассоциация может иметь больше смысла. Но я не знаю о них много, есть ли причина, по которой я не хотел бы их использовать, или что ИППП лучше? Кажется, что они абсолютно одинаковы, за исключением того, что поля, относящиеся к родителям или бизнесу, хранятся в отдельных таблицах, что, как мне кажется, и было бы желательным. Не так ли?

Ответы [ 5 ]

3 голосов
/ 02 апреля 2010

Я считаю, что в данной ситуации лучше всего подойти:

  • создать таблицу для хранения пользователей обоих типов; в этой таблице будет столбец для каждого свойства, которое разделяют два типа пользователей;
  • создать вспомогательную таблицу для каждого типа с внешним ключом, указывающим на таблицу «Пользователи»; эти таблицы будут иметь только дополнительные свойства для каждого типа плюс внешний ключ для пользователей;

Таким образом, вы избежите проблем с нехваткой данных в вашей БД и будете иметь только столько записей в таблицах расширений, сколько существует пользователей этого типа. Если вы используете инструмент генерации кода, вы можете сгенерировать для каждой таблицы расширений, которая затем будет иметь User в качестве родительского свойства, что позволит вам получить доступ ко всем полям. Возможно, вы также захотите сгенерировать для самой таблицы пользователей, когда вы обрабатываете всех пользователей независимо от их типа.

Надеюсь, это имеет смысл и помогает.

Ура! * * 1013

1 голос
/ 03 апреля 2010

Моделирование отношений в базе данных добавляет много сложности. Например, для вспомогательной таблицы (или отношения 1: 1) требуется join в каждом запросе:

select u.name, p.DomesticPartner
from users u
join users_partners p on p.userId = u.id

Динамический столбец (1: множество именных пар значений) добавляет один join к КАЖДОМУ столбцу, который вы запрашиваете:

select n.value as Name, p.value as DomesticPartner
from users u
join users_columns n on n.name = 'Name' and n.userid = u.id
join users_columns p on p.name = 'DomesticPartner' and p.userid = u.id

Вы должны сравнить эту сложность с добавленной стоимостью, которую обеспечивает отношение.

Для себя, как правило, я избегаю отношений с базой данных, если для этого нет веских причин. Пример веских причин:

  • Не зная имен столбцов во время разработки
  • Размер строки будет превышать максимально допустимый базой данных
  • Отношение само моделирует информацию (например, клиенты и заказы)

В вашем случае я бы просто добавил все столбцы в пользовательскую таблицу. Вы можете принудительно установить, что неиспользуемые столбцы должны быть нулевыми, используя ограничение check:

CHECK (UserType = 'Parent' OR DomesticPartner IS NULL)
1 голос
/ 02 апреля 2010

В объектно-ориентированной среде это моделируется с помощью наследования. Есть несколько способов отобразить наследование в таблицы базы данных. Наиболее простым является наследование одной таблицы . Если у вас есть объектно-ориентированная среда, потребляющая базу данных, это стоит изучить.

Обновление: ИППП против других альтернатив

Если количество полей, которые отличаются, невелико, я бы выбрал STI, поскольку это просто реализовать и не добавляет необходимости в дополнительных объединениях. Двумя другими основными альтернативами являются

  • Таблица на класс
  • Таблица по классу бетона

Таблица для каждого класса

Если есть много полей, которые отличаются между типами, это предпочтительнее. Недостатком является то, что почти для всех запросов потребуются операции соединения между таблицей базовых классов и одной или несколькими таблицами подклассов.

Таблица по классу бетона

Исправить проблему объединения таблицы на класс. Таблица на конкретный класс - это еще один способ. Однако требуется, чтобы общие поля, принадлежащие абстрактному базовому классу, присутствовали в нескольких таблицах. Это нарушает принцип DRY и требует объединения запросов для получения общих свойств от нескольких конкретных типов.

1 голос
/ 02 апреля 2010

Как правило, у вас есть таблица «Пользователи», в которой есть все поля, общие для родителей и компаний, а также уникальный идентификатор, называемый идентификатором пользователя. Затем в таблице «Родители» у вас будет идентификатор пользователя (для ссылки на таблицу «Пользователи») и поля, которые являются уникальными для родителей. Точно так же у вас будет таблица «Бизнес» с полем «UserID» и полями, уникальными для компаний. Вот так вы бы настроили нормализованную базу данных. Поля UserID в таблицах «Родители и бизнес» будут ссылками (внешним ключом) на таблицу «Пользователи».

0 голосов
/ 03 апреля 2010

Взгляните на этот вопрос / ответ с похожей проблемой, он описывает отношение супертип / подтип.

...