Первичный ключ против уникального ограничения? - PullRequest
44 голосов
/ 01 октября 2008

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

Я прочитал много статей / дискуссий / сообщений в группах новостей, в которых говорится, что вместо PK лучше использовать уникальное ограничение (он же уникальный индекс для некоторой базы данных).

Какова ваша точка зрения?

Ответы [ 16 ]

46 голосов
/ 01 октября 2008

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

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

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

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

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

  • Редактировать: Указывалось, что термин «кластеризованная таблица» и «кластеризованный индекс» у Oracle отличается от Sql Server. Эквивалентом того, о чем я говорю в Oracle-ese, является Индексная упорядоченная таблица , и она рекомендуется для таблиц OLTP - что, я думаю, было бы основным вопросом SO. Я предполагаю, что если вы отвечаете за большое хранилище данных OLAP, у вас уже должно быть собственное мнение о проектировании и оптимизации базы данных.

38 голосов
/ 01 октября 2008

Можете ли вы дать ссылки на эти статьи?

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

Использование UNIQUE для достижения той же цели звучит для меня по-настоящему хакерски. Каково их обоснование?

Редактировать: мое внимание только что вернулось к этому старому ответу. Возможно, дискуссия, которую вы читали о PK против UNIQUE, касалась людей, делающих что-то вроде PK с единственной целью придания ему уникальности. Ответ на этот вопрос: если это ключ, то сделайте его ключом, иначе сделайте его УНИКАЛЬНЫМ.

10 голосов
/ 01 октября 2008

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

Я ожидаю, что люди, которые спорят с ними, не видят причин обращаться с одним ключом иначе, чем с другим. Вот где я стою.

[Редактировать] Очевидно, я не могу комментировать даже свой собственный ответ без 50 баллов.

@ Крис: Я не думаю, что есть вред. «Первичный ключ» на самом деле просто синтаксический сахар. Я использую их все время, но я не думаю, что они необходимы. Требуется уникальный ключ , но не обязательно первичный ключ.

9 голосов
/ 01 октября 2008

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

Уникальное ограничение будет использоваться, если вы хотите гарантировать уникальность столбца в ДОПОЛНЕНИИ к первичному ключу.

Правило всегда иметь ПК является хорошим.

http://msdn.microsoft.com/en-us/library/ms191166.aspx

5 голосов
/ 01 октября 2008

Вы должны всегда иметь первичный ключ.

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

Этот вопрос - вековая религиозная война в области БД.

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

3 голосов
/ 01 октября 2008

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

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

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

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

4 - многим интерфейсным средам разработки требуется первичный ключ для обновления таблицы или удаления.

3 голосов
/ 01 октября 2008

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

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

2 голосов
/ 01 октября 2008

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

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

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

Кроме того, некоторые РСУБД предоставляют дополнительные функции, если первичные ключи правильно помечены, такие как создание диаграмм и полуавтоматическая поддержка ограничения внешнего ключа.

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

1 голос
/ 24 июня 2015

ПЕРВИЧНЫЙ КЛЮЧ

1. Null Он не допускает пустых значений. Из-за этого мы называем ПЕРВИЧНЫЙ КЛЮЧ = УНИКАЛЬНЫЙ КЛЮЧ + НЕ НУЛЯЕТ ОГРАНИЧЕНИЕ. 2. INDEX По умолчанию он добавляет кластерный индекс. 3. LIMIT Таблица может иметь только один столбец PRIMARY KEY [s].

УНИКАЛЬНЫЙ КЛЮЧ

1. Null Позволяет нулевое значение. Но только одно значение Null. 2. INDEX По умолчанию он добавляет УНИКАЛЬНЫЙ некластеризованный индекс. 3. LIMIT В таблице может быть несколько столбцов UNIQUE Key [s].

1 голос
/ 02 октября 2008

Я много писал на эту тему: если вы прочитали что-нибудь из моих, ясно, что я, вероятно, имел в виду именно Jet a.k.a. MS Access.

В Jet таблицы физически упорядочены на ПЕРВИЧНОМ КЛЮЧЕ с использованием необслуживаемого кластеризованного индекса (кластеризован на компактном). Если в таблице нет PK, но ключи-кандидаты определены с использованием ограничений UNIQUE для столбцов NOT NULL, то механизм выберет один для кластеризованного индекса (если в вашей таблице нет кластеризованного индекса, то он называется кучей, возможно, не таблицей вообще !) Как двигатель выбирает подходящий ключ? Может ли он выбрать тот, который включает обнуляемые столбцы? Я действительно не знаю. Дело в том, что в Jet единственным явным способом указания кластерного индекса для движка является использование PRIMARY KEY. Конечно, есть и другие варианты использования PK в Jet, например, он будет использоваться в качестве ключа, если он пропущен в объявлении FOREIGN KEY в SQL DDL, но, опять же, почему бы не быть явным.

Проблема с Jet заключается в том, что большинство людей, которые создают таблицы, не знают о кластерных индексах или не заботятся о них. Фактически, большинство пользователей (я держу пари) помещает столбец автоинкремента автоинкремента в каждую таблицу и определяет PRIMARY KEY исключительно для этого столбца, не устанавливая никаких уникальных ограничений на естественный ключ и ключи-кандидаты (может ли столбец автоинкремента фактически рассматриваться как ключ, не раскрывая его конечным пользователям, сам по себе является еще одной дискуссией). Я не буду вдаваться в подробности о кластеризованных индексах здесь, но достаточно сказать, что ИМО - единственный столбец автоинкремента - редко является идеальным выбором.

Независимо от того, какой у вас движок SQL, выбор PRIMARY KEY произвольный и зависит от движка. Обычно движок придает особое значение PK, поэтому вы должны выяснить, что это такое, и использовать его в своих интересах. Я призываю людей использовать ограничения NOT NULL UNIQUE в надежде, что они будут уделять больше внимания всем ключам-кандидатам, особенно когда они решили использовать столбцы «autonumber», которые (не должны) иметь значение в модели данных. Но я бы предпочел, чтобы народ выбрал один хорошо продуманный ключ и использовал ПЕРВИЧНЫЙ КЛЮЧ, а не ставил его в колонку автоинкремента по привычке.

Должны ли все таблицы иметь PK? Я говорю «да», потому что если вы поступите иначе, по крайней мере, вы упустите небольшое преимущество, которое дает движок PK, и в худшем случае у вас нет целостности данных.

КСТАТИ Крис OC делает хорошее замечание о временных таблицах, которые требуют последовательных первичных ключей (нижний регистр), которые не могут быть реализованы с помощью простых ограничений PRIMARY KEY (ключевые слова SQL в верхнем регистре).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...