2012-06-11 6 views
50

У меня есть таблица «Пользователь» (имя пользователя, пароль) и таблица «Профиль» (profileId, пол, дата рождения, ...). В настоящее время я использую этот подход: каждая запись профиля имеет поле с именем «userId» в качестве внешнего ключа, который ссылается на таблицу «Пользователь». Когда пользователь регистрируется, его запись профиля автоматически создается. Я путаюсь с предложением моего друга: иметь поле «userId» в качестве внешнего и первичного ключа и удалять поле «profileId». Какой подход лучше?Хорошо ли иметь внешний ключ в качестве первичного ключа?

+2

Entity Framework генерирует это (с первым кодом) для отношений zeroOrOne (и одного) -от одного. Так ... это возможно. Это лучший способ ... Это другой вопрос. Но это действительно так. Я никогда не делал этого, создавая свои собственные базы данных (но я даже и не думал об этом). –

ответ

66

Внешние ключи почти всегда «Разрешить Дубликаты», который сделает их непригодными в качестве первичных ключей.

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

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

+25

Комбинированный первичный ключ, состоящий из двух внешних ключей, также отлично подходит для реализации отношений «многие ко многим». – rightfold

+0

@ rightfold, вы спасли день, спасибо. – Yahya

1

Я бы этого не сделал. Я хотел бы сохранить в качестве первичного ключа таблицы Profile

profileID Внешний ключ просто реляционная между двумя таблицами

Можно утверждать, что первичный ключ необходим в качестве цели любых внешних ключей, которые ссылаются к нему из других таблиц. Внешний ключ - это набор из одного или нескольких столбцов в любой таблице (не обязательно ключ-кандидат, не говоря уже о первичном ключе этой таблицы), который может содержать значения (-и), найденные в столбцах (-ях) первичного ключа некоторых другой таблица. Поэтому у нас должен быть первичный ключ для соответствия внешнему ключу. Или мы должны? Единственная цель первичного ключа в паре первичного ключа/внешнего ключа - обеспечить однозначное соединение - поддерживать ссылочную целостность по отношению к «чужой» таблице, которая содержит ссылочный первичный ключ. Это гарантирует, что значение, к которому относится внешний ключ, всегда будет действительным (или null, если разрешено).

http://www.aisintl.com/case/primary_and_foreign_key.html

+0

Возможно - если у вас есть ограничение FK между User.UserID и Profile.UserID, тогда настоятельно рекомендуется иметь индекс в Profile.UserID. Почему бы не сделать, чтобы первичный кластерный индекс в профиле таблицы сохранял второй индекс и много ненужной работы для механизма базы данных? – DaveBoltman

21

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

1

Это зависит от бизнеса и системы.

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

4

Как правило, считается неправильной практикой иметь отношения «один к одному». Это связано с тем, что вы можете просто представить данные, представленные в одной таблице, и добиться того же результата.

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

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

+2

Я согласен с вами в основном в том, что есть много преимуществ для того, чтобы все данные в той же таблице, что и дополнительные столбцы. Хотя w.r.t это ... «вы могли бы просто иметь данные, представленные в одной таблице, и добиться того же результата» ..: может быть полезно иметь отдельную таблицу, например здесь, если запись в таблице профиля является необязательной. Например, у каждого банковского клиента может не быть регистрации в интернет-банке. В этом случае таблица регистрации IB может использоваться, чтобы ограничить другие таблицы дополнительными дочерними записями. Опять же, здесь это можно сделать и с новым ПК для таблицы регистрации IB. – Teddy

+1

@ Teddy Аналогично, я в основном согласен с тем, что вы сказали. Однако в исходном вопросе они заявляют: «... его запись профиля автоматически создается ...», подразумевая, что таблица профилей не является необязательной. В ситуации, когда таблица профилей была опциональной, тогда да, имея ее как отдельную таблицу, выполнимо. Но опять же, они могли бы просто использовать столбцы с нулевым значением в одной таблице. – Tshsmith

+1

Используя отдельную вторую таблицу, мы можем предотвратить запись в третьей таблице, которая разрешена только для людей, у которых есть запись во второй таблице. – Teddy

0

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

1

Да, это законно, чтобы иметь первичный ключ является внешним ключом. Это редкая конструкция, но она применяется для:

  • a соотношение 1: 1. Две таблицы не могут быть объединены в одну из-за того, что разные разрешения и привилегии применяются только на уровне таблицы (по состоянию на 2017 г. такая база данных будет нечетной).

  • a 1: 0..1 отношение. Профиль может или не может существовать в зависимости от типа пользователя.

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