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

341

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

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

Даниэль Сильвейра
источник
5
Не могли бы вы дать более подробную информацию о столе? Ответ, вероятно, "да", хотя.
Райан Бэйр
7
Да, каждая таблица должна иметь первичный ключ.
Сайед Тайяб Али

Ответы:

314

Краткий ответ: да .

Длинный ответ:

  • Вам нужно, чтобы ваш стол был чем-то совместимым
  • Если вы хотите, чтобы ваша таблица была кластеризована, вам нужен какой-то первичный ключ.
  • Если вашему дизайну таблицы не нужен первичный ключ, переосмыслите свой дизайн: скорее всего, вы что-то упустили. Зачем вести одинаковые записи?

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

Обратите внимание, что первичный ключ может быть составным.

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

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

А поскольку любой первичный ключ включает создание уникального индекса, вы должны объявить его и получить как логическую согласованность, так и производительность.

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

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

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

Quassnoi
источник
у них все еще есть первичный ключ, составной
kristof
2
@annakata: у них должен быть составной первичный ключ
Quassnoi
1
«А поскольку любой PRIMARY KEY предполагает создание УНИКАЛЬНОГО индекса», это неверно для Oracle. Можно использовать неуникальный индекс для обеспечения первичного ключа. Фактически иногда ТРЕБУЕТСЯ, чтобы ограничения уникальности и PK использовали неуникальные индексы.
Стефани Пейдж
3
Просто комментарий к риторическому вопросу «Зачем вести одинаковые записи?». Обратите внимание, что простое добавление PK не гарантирует отсутствие дублирования. Часто PK не виден пользователю, поэтому важно то, что находится в видимых полях, которые могут содержать дублирующиеся данные. В зависимости от вашего дизайна это может быть желательно или нет.
Росско
1
Ключи не имеют ничего общего с присоединяемостью. И аргумент кластеризации зависит от того, какую СУБД вы используете, и сочетает логические и физические соображения.
Джон Хеггланд
36

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

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

Майкл Уилер
источник
5
@PaulSuart Данные не всегда должны быть в их нормальном виде. Фактически, когда данные становятся огромными, их не следует хранить в их обычной форме, иначе доступ к данным будет ужасно медленным для запросов, выполняющих объединения таблиц и т. Д. Нормальные формы - это «идеализация» и практически возможны только тогда, когда данные не будут расти огромно.
Pacerier
13

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

tvanfosson
источник
13
Таблица соединений - это первичный ключ - составной, состоящий из PK обеих записей, которые объединяются. Например, CREATE TABLE PersonOrder (PersonId int, OrderId int, ПЕРВИЧНЫЙ КЛЮЧ (PersonId, OrderId)).
Кит Уильямс
3
Да, но что если таблица ссылок имеет также третий атрибут, скажем, «OrderDate». Вы бы добавили это и в составной ключ? ИМХО нет - потому что он еще более сводим и не служит неприводимым признаком, который должен иметь первичный ключ.
Stevek
13

За исключением нескольких очень редких случаев (возможно, таблицы отношений «многие ко многим» или таблицы, которую вы временно используете для массовой загрузки огромных объемов данных), я бы сказал:

Если у него нет первичного ключа, это не таблица!

Марк

marc_s
источник
10
Строго говоря, это предложение неверно. Таблицы могут быть «Просмотреть таблицы», созданные вашим языком запросов. СУБД состоит из отношений, а не таблиц. В этом предложении должно быть сказано: «Если у него нет первичного ключа, это не отношение!».
Stevek
Или, возможно, «если нет ключей-кандидатов, то это не реляционная таблица». Но посмотрите на очень редкие случаи, когда нормально иметь таблицу, которая не представляет отношения.
Уолтер Митти
Почему таблица «многие ко многим» не имеет первичного ключа? Вы можете создать отдельный первичный ключ, а затем создать уникальный индекс для суррогата внешних ключей. Я думаю, что лучше иметь первичный ключ на каждом столе. Даже в таблице массовой загрузки может потребоваться отдельно определить первичный ключ, который не включает импортируемые данные, поскольку он может помочь вам идентифицировать дубликаты записей в процессе ETL. Мне кажется, что у каждой таблицы должен быть первичный ключ, даже если он немного больше памяти. Таблица, созданная представлением, является подмножеством таблицы, а не самой таблицей.
Джон Эрнест
1
В таблице отношений «многие ко многим» вы можете создать составной первичный ключ, состоящий из обоих идентификаторов отношений.
Яап
8

Просто добавьте его, вы будете сожалеть позже, когда вы этого не сделали (выбор, удаление. Ссылки и т. Д.)

raphaëλ
источник
8

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

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

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

HLGEM
источник
6

Рекомендуется иметь ПК на каждом столе, но это НЕ ДОЛЖНО. Скорее всего, вам понадобится уникальный индекс и / или кластерный индекс (который является PK или нет) в зависимости от ваших потребностей.

Ознакомьтесь с разделами «Основные ключи» и «Кластерные индексы» в электронной документации (для SQL Server)

« Ограничения PRIMARY KEY идентифицируют столбец или набор столбцов, которые имеют значения, которые однозначно идентифицируют строку в таблице. Никакие две строки в таблице не могут иметь одинаковое значение первичного ключа. Вы не можете ввести NULL для любого столбца в первичном ключе. Мы Рекомендуется использовать небольшой целочисленный столбец в качестве первичного ключа. Каждая таблица должна иметь первичный ключ. Столбец или комбинация столбцов, которые квалифицируются как значение первичного ключа, упоминаются как ключ-кандидат. "

Но затем проверьте это также: http://www.aisintl.com/case/primary_and_foreign_key.html

endo64
источник
1
Проверьте это также, sql-server-performance.com/2006/primary-key-index-clustered
endo64
4
эта страница довольно глупая. Во-первых, первичный ключ необходим для повышения производительности. Читая его страницу, я узнаю, что добавление идентификатора в таблицу книг бесполезно, поскольку текст книги уникален; очевидно, парень никогда не работал с базами данных. Но у него также есть проблемы в понимании того, что он критикует. На странице написано, что 1) значение PK ссылается на строку 2) вы можете объединить 2 таблицы по любому набору столбцов. Противоречия нет. Удивительно, что автор академической статьи не понимает основы теории отношений.
Федерико Раззоли,
1
«Во-первых, первичный ключ необходим для повышения производительности», это неверно, PK не влияет напрямую на производительность. Отсутствие PK может привести к множеству проблем (определение строки, присоединение и т. Д.), Но производительность не является одной из них. Когда вы создаете PK на таблице, SQL-сервер создает уникальный кластеризованный индекс, этот индекс влияет на производительность, а не на сам PK. В качестве реального примера моя таблица имеет кластерный индекс по столбцу даты и PK в поле GUID, потому что мои строки должны быть физически упорядочены по столбцу даты в таблице, поскольку все запросы имеют диапазон дат (в моем случае).
endo64
Этот кластерный индекс является разновидностью первичного ключа, созданного SQL Server и несколькими другими СУБД. Вы уверены, что это хорошая идея? Например, в MySQL это не по нескольким недокументированным причинам.
Федерико Раззоли
1
Имейте в виду, что GUID не является оптимальным типом для PK в InnoDB. Все индексы содержат ссылку на PK, поэтому чем больше PK, тем больше будут все остальные индексы.
Федерико Раззоли
6

Не согласен с предложенным ответом. Короткий ответ: НЕТ .

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

Однако существуют случаи, например, регистрация данных временных рядов, когда существование такого ключа просто не требуется и просто занимает память. Создание уникального ряда просто ... не требуется!

Небольшой пример: Таблица A: LogData

Columns:  DateAndTime, UserId, AttribA, AttribB, AttribC etc...

Первичный ключ не требуется.

Таблица B: Пользователь

Columns: Id, FirstName, LastName etc. 

Первичный ключ (Id) необходим для использования в качестве «внешнего ключа» для таблицы LogData.

Теодор Зографос
источник
3

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

Tacoman667
источник
3

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

StewNoble
источник
Я еще не уверен, что это необходимо, но «сделайте это, потому что в противном случае кому-то придется столкнуться с последствиями позже», этого достаточно, чтобы заставить меня ошибиться. Я всегда могу просто опустить столбец позже, если кажется, что стоит попытаться уменьшить его ...
ArtOfWarfare
3

Я нахожусь в роли поддержки приложения, созданного оффшорной командой разработчиков. Теперь у меня возникают всевозможные проблемы в приложении, потому что исходная схема базы данных не содержала ПЕРВИЧНЫЕ КЛЮЧИ в некоторых таблицах. Поэтому, пожалуйста, не позволяйте другим людям страдать из-за вашего плохого дизайна. Всегда полезно иметь первичные ключи на таблицах.

Шива
источник
2

У меня всегда есть первичный ключ, даже если вначале у меня еще не было цели для него. Было несколько раз, когда мне в конце концов понадобился ПК в таблице, в которой его нет, и всегда сложнее вставить его позже. Я думаю, что есть преимущество в том, чтобы всегда включать один.

rvarcher
источник
1

Короче нет. Однако необходимо помнить, что некоторые операции CRUD для клиентского доступа требуют этого. Для проверки будущего я обычно использую первичные ключи.

Rich.Carpenter
источник
1

Если вы используете Hibernate, то невозможно создать сущность без первичного ключа. Эти проблемы могут создать проблему, если вы работаете с существующей базой данных, которая была создана с помощью простых сценариев sql / ddl, и первичный ключ не был добавлен

Schildmeijer
источник