Должен ли первичный ключ быть неизменным?

26

Недавний вопрос о StackOverflow вызвал дискуссию о неизменности первичных ключей. Я думал, что это своего рода правило, что первичные ключи должны быть неизменными. Если есть вероятность, что когда-нибудь первичный ключ будет обновлен, я подумал, что вы должны использовать суррогатный ключ. Однако это не входит в стандарт SQL, и некоторые функции «каскадного обновления» СУБД позволяют изменять первичный ключ.

Поэтому мой вопрос: все еще плохая практика иметь первичный ключ, который может измениться? Каковы недостатки наличия изменяемого первичного ключа?

Винсент Малграт
источник

Ответы:

25

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

С другой стороны, вам нужен только изменяемый ключ, если он содержит некоторую информацию, которая может измениться. Я всегда использую суррогатный ключ, если запись не имеет простого неизменного идентификатора, который можно использовать в качестве ключа.

Guffa
источник
7
Почему вам « нужен первичный ключ, который должен быть неизменным, если он связан с внешним ключом»? Как упоминалось в OP, большинство РСУБД имеют функцию «каскадного» обновления.
Танатос
1
@Tanatos большинство (на самом деле все, с чем я сталкивался) rdbms не позволяют изменяемые первичные ключи, но имеют каскадные обновления. Первичный ключ, в общепринятом понимании DBA, не должен содержать никакой информации, быть только уникальным идентификатором записи (таким образом, даже не отметка времени, отложенный диапазон записей и т. Д.).
С
5
@jwenting: мы говорим об одном и том же? "большинство rdbms не допускает изменяемые первичные ключи" включает что? Как MySQL, так и PostgreSQL допускают изменяемые первичные ключи и поддерживают каскадные обновления… как я думаю, стандартный SQL говорит, что они должны это делать Кроме того, "общепринятая мудрость DBA"? Я встречал множество администраторов баз данных, которые выступают против суррогатных ключей, и множество администраторов, которые спорят с естественными ключами.
Танатос
2
@Tanatos Аргументы в пользу «все таблицы должны иметь суррогатное» не содержат библиографических ссылок, они ссылаются на «общепринятую мудрость DBA», но никогда не ссылаются на книгу. В канонических книгах говорится, что вы должны использовать суррогат, если: A. естественного ключа не существует, B. многоколоночный ключ превышает 3 столбца или C. Вы будете менять ключ все время. Итак: естественные, когда они подходят, суррогаты, когда натуральные не подходят.
Тулаинс Кордова
4
@ user61852: Что?
Гуффа
15

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

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

Крис Холмс
источник
15

Да, по моему мнению первичный ключ должен быть неизменным.

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

richeym
источник
Хороший вопрос об ошибках ввода данных
Тим Гудман
Ричейм, похоже, что вы делаете пример, почему ключи НЕ должны быть неизменными: пользователи могут захотеть изменить их.
nvogel
4
@dportas - моя точка зрения заключается в том, что мне нравится, что PK являются неизменяемыми, поэтому всегда используйте суррогатные ключи, даже если я думаю, что есть очевидный ключ, который можно извлечь из данных таблицы (например, электронная почта, имя пользователя).
Ричейм
2

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

spoulson
источник
2

Почему бы нет? Потому что вы хотите устранить столбец?

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

Мне не платят за каждое каскадное обновление, которое я внедряю, и бонус, если я сам его кодирую.

Компьютер не требует никакого значения для ключа; ИМХО, ключи для компьютеров, пусть люди испортят остальные данные.

JeffO
источник
1
«ключи для компьютеров, пусть люди облажаются с остальными данными». +1, приятно.
2

Неплохая практика иметь ключ, значения которого могут измениться.

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

Возьмите пример международного стандартного номера книги (ISBN) . Она очень стабильна, но не неизменна: иногда издатели книг совершают ошибки и - ужас! - могут встречаться дублирующие номера ISBN. Означает ли это, что ISBN не следует принимать в качестве ключа-кандидата в компьютеризированной базе данных? Конечно нет. Одним из преимуществ ISBN является то, что он имеет надежный источник, который решает проблемы для всех пользователей во всем мире.

Есть и другие свойства хорошего ключа, которые есть у ISBN, которых будет лишен бессмысленный автоинкрементный целочисленный ключ, например, фамильярность (все в книжной торговле знают или знакомы с ISBN), проверяемая (ISBN напечатан на всех современных книгах), может проверяться со ссылкой на СУБД (ISBN имеет фиксированную ширину и включает контрольную сумму) и т. д.

onedaywhen
источник
3
ISBN является фиксированной шириной, за исключением случаев, когда это не так (см. ISBN-10 против ISBN-13).
CVN
Итак, как бы вы порекомендовали обрабатывать дубликаты ISBN? Во всех РСУБД, о которых я знаю, вам необходимо иметь УНИКАЛЬНОЕ ограничение на поле, чтобы использовать его в качестве первичного ключа.
Wildcard
1

Все, что может быть неизменным, должно быть. Это помогает гарантировать правильность и помогает, когда вы хотите сделать ваше приложение многопоточным.

штрих-кот-бэнг
источник
1

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

Боб Джарвис - Восстановить Монику
источник
0

Как уже говорилось в некоторых комментариях, одним из решений является использование нового первичного ключа

Например (следуя примеру @onedaywhen), предположим, что существует таблица Books которой хранится список книг, и мы «использовали» ее для определения ISBN в качестве первичного ключа. Однако некоторые авторы допустили ошибку, набрав неправильный ISBN, поэтому они попросили изменить ISBN, это включало следующие задачи:

  • создать новый реестр в таблице Книги
  • Укажите все ссылки со старого ISBN на новый ISBN. (*)
  • И наконец, удалите старый реестр из таблицы Книги.

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

Table Books
ISBN  is the primary key
NAME is a simple field.
etc.

Мы меняем это как

Table Books
InternalBookId as the primary key
ISBN as a simple field or an indexed field.
NAME is a simple field.
etc.

Где новый InternalBookId может быть даже числовым значением.

Минусы по этому поводу:

  • это добавляет новое поле, которое использует больше места / ресурса.

  • это может потребовать переписать всю модель.

  • новая модель может быть менее самообъяснимой.

Про

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

Новая таблица:

Table Books
InternalBookId as the primary key
ISBN13 is a new field.
NAME is a simple field.
etc.
Магеллана
источник