Разобраться с таблицей, это составной первичный ключ, я хотел включить обнуляемый столбец - PullRequest
0 голосов
/ 07 августа 2011

Допустим, таблица может выглядеть следующим образом:

userId INT (foreign key to a users table)
profileId INT (foreign key to a profiles table)
value INT

Скажите, что в этой таблице сохранены настройки для пользователей.Предпочтение должно быть загружено в соответствии с текущим пользователем и профилем, выбранным текущим пользователем.Это означает, что комбинация userId и profileId является уникальной и может использоваться в качестве составного первичного ключа.

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

Так, каков «лучший» способ работывокруг этого?Просто сбросить первичный ключ полностью и обойтись без первичного ключа?Генерировать столбец идентификаторов в качестве первичного ключа, который мне никогда не нужен?Создать фиктивный профиль для ссылки в таблице профилей?Создать отдельную таблицу для значений по умолчанию (которая является единственной опцией, гарантирующей, что ни один userId не имеет нескольких значений по умолчанию ??)?

Обновление: я думал об ответе Дмитрия, но в конце концов у него есть недостаток, который яневозможно даже создать уникальное ограничение для двух столбцов userId и profileId (MySQL разрешит дублирование значений, если profileId равен нулю, а DB2 откажется даже создать уникальное ограничение для столбца, допускающего пустые значения).Так что с решением Дмитрия мне придется жить без проверки целостности БД.Это приемлемо?Или это неприемлемо (после всех проверок согласованности является основной особенностью реляционных БД)Каково ваше мнение?

Ответы [ 4 ]

2 голосов
/ 07 августа 2011

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

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

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

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

2 голосов
/ 07 августа 2011
  1. Создать поле автоинкремента идентификатора для вашего первичного ключа.

AND

  1. Создать уникальный индекс для пары (userId, profileId).При необходимости создайте фиктивный профиль вместо нуля.
1 голос
/ 25 января 2012

Это нормальное поведение ограничения UNIQUE для столбца NULL. Это позволяет одну строку данных со значениями NULL. Однако это не то поведение, которое мы хотим для этого столбца. Мы хотим, чтобы столбец принимал уникальные значения, а также принимал несколько значений NULL.

Этого можно достичь, используя вычисляемый столбец и добавив в вычисляемый столбец ограничение вместо значения по умолчанию, равного NULL.

См. Ниже статью поможет вам больше в этом вопросе:

УНИКАЛЬНЫЙ столбец с несколькими значениями NULL

0 голосов
/ 25 января 2012

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

create table UserProfile ( int UserProfileID auto_increment primary key etc., 
    UserID int not null, ProfileID int );

Затем создайте вторичный индекс UserProfileIDX (UserID, ProfileID), который является уникальным, но не первичный ключ.

...