Должны ли внешние ключи использоваться в структуре, где пользователь может выбрать несколько вариантов?Если так, то как? - PullRequest
1 голос
/ 05 октября 2011

В MySQL мне посоветовали хранить опции множественного выбора для «Наркотиков» в виде отдельной таблицы user_drug, где каждая строка - это одна из опций, выбранных конкретным пользователем. Мне также посоветовали создать третью таблицу drug, которая описывает каждый параметр, выбранный в таблице user_drug. Вот пример:

user
id    name  income
1     Foo   10000
2     Bar   20000
3     Baz   30000

drug
id    name
1     Marijuana
2     Cocaine
3     Heroin

user_drug
user_id drug_id
1       1
1       2
2       1       
2       3
3       3

Как видите, таблица user_drug может содержать несколько лекарств, выбранных конкретным пользователем, а таблица drug сообщает вам, к какому препарату относится drug_id.

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

Не проще ли избавиться от таблицы лекарств и просто сохранить значение TEXT для каждого лекарства в user_drug? Почему или почему нет?

Если добавление 3-й таблицы drug лучше, то как мне реализовать структуру внешнего ключа и как обычно получать соответствующие значения, используя эти внешние ключи?

(мне кажется, гораздо проще использовать только 2 таблицы, но я слышал, что внешние ключи полезны тем, что они обеспечивают правильное ввод значения и что поиск и сортировка * 1027 также намного быстрее * чем текстовое значение, поэтому я хочу быть уверен.)

Ответы [ 2 ]

3 голосов
/ 05 октября 2011

Не проще ли избавиться от таблицы лекарств и просто сохранить значение TEXT для каждого лекарства в user_drug? Почему или почему нет?

Проще, да.
Но не лучше

  1. Ваши данные не будут нормализованы, тратя много места на хранение таблицы.
  2. Индекс в этом поле занял бы гораздо больше места, снова занимая место и замедляя процесс.
  3. Если вы хотите запросить раскрывающийся список возможных значений, это тривиально с отдельной таблицей, трудно (читай: медленно) с просто текстом в поле.
  4. Если вы просто отбросите текстовые поля в 1 таблице, трудно будет гарантировать, что орфографические ошибки туда не попадут, а отдельная таблица ссылок предотвращает орфографические ошибки.

Если добавить препарат 3-го стола лучше, , тогда как бы я внедрил структуру внешнего ключа

ALTER TABLE user_drug ADD FOREIGN KEY fk_drug(drug_id) REFERENCES drug(id);

и как я обычно получаю соответствующие значения, используя эти внешние ключи?

SELECT u.name, d.name as drug
FROM user u
INNER JOIN user_drug ud ON (ud.user_id = u.id)
INNER JOIN drug d ON (d.id = ud.drug_id)

Не забудьте объявить первичный ключ для таблицы user_drug как

PRIMARY KEY (user_id, drug_id)

С другой стороны
Вы можете использовать перечисление

CREATE TABLE example (
  id UNSIGNED INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  example ENUM('value1','value2','value3'),
  other_fields .....

Вы не получаете всех преимуществ отдельной таблицы, но если вам просто нужно несколько значений (например, yes/no или male/female/unknown), и вы хотите убедиться, что оно ограничено только эти ценности, это хороший компромисс.
И гораздо более самодокументируемый и устойчивый, чем магические константы (1 = мужской, 2 = женский, 3 = неизвестный, ... но что произойдет, если мы вставим 4?)

1 голос
/ 05 октября 2011

Не проще ли избавиться от таблицы лекарств и просто сохранить значение ТЕКСТ каждого лекарства в user_drug?Почему или почему нет?

Обычно у вас в таблице лекарств будет много других столбцов - таких как описание, медицинская информация, химические свойства и т. Д. В этом случае вы не захотитехочу дублировать всю эту информацию в каждой записи таблицы user_drug.В данном конкретном случае, однако, у вас есть только один столбец, так что эта проблема на самом деле не имеет большого значения.

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

...