Зачем использовать несколько столбцов в качестве первичных ключей (составной первичный ключ)

109

Этот пример взят из w3schools .

CREATE TABLE Persons
(
    P_Id int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255),
    CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
)

Насколько я понимаю, оба столбца вместе ( P_Idи LastName) представляют собой первичный ключ для таблицы Persons. Это верно?

  • Зачем кому-то нужно использовать несколько столбцов в качестве первичных ключей вместо одного столбца?
  • Сколько столбцов можно использовать вместе как первичный ключ в данной таблице?
rockbala
источник
... теперь есть ответ и на 2-й вопрос
Wolf
1
@Martijn Peters. Почему был удален ответ?
PerformanceDBA

Ответы:

119

Ваше понимание правильное.

Вы бы сделали это во многих случаях. Один пример - такие отношения, как OrderHeaderи OrderDetail. ПК OrderHeaderможет быть OrderNumber. PK в OrderDetailможет быть OrderNumberAND LineNumber. Если бы это был один из этих двух, он не был бы уникальным, но их комбинация гарантированно уникальна.

Альтернативой является использование сгенерированного (неинтеллектуального) первичного ключа, например, в этом случае OrderDetailId. Но тогда вы не всегда будете видеть отношения так легко. Некоторые люди предпочитают один путь; некоторые предпочитают другой путь.

MJB
источник
2
Это полезно, если я использую branch_id и использую репликацию между двумя базами данных, чтобы решить проблему дублирования идентификаторов? !!
Mhmd
11
Обратите внимание, что во многих случаях использования сгенерированного первичного ключа вам часто все же нужен уникальный ключ для составных значений.
Bacon Bits
Уточните, пожалуйста, «Некоторые люди предпочитают один путь, некоторые - другой».
Имя пользователя
1
Просьба уточнить? Не знаю, что сказать. Я знаю людей, которые предпочитают использовать несколько объединенных полей в качестве ключа, потому что им легче интуитивно понять, на что они смотрят. Я знаю других, которые предпочитают просто назначать уникальный ключ каждой строке, потому что его проще и быстрее набирать. Вы об этом спрашиваете?
MJB
Это сообщение предназначалось для @Username. Я забыл направить его.
MJB
26

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

Create Table Person(
PersonID int Not Null,
FirstName varchar(50),
LastName varchar(50),
Constraint PK_Person PRIMARY KEY (PersonID))

Create Table Group (
GroupId int Not Null,
GroupName varchar(50),
Constraint PK_Group PRIMARY KEY (GroupId))

Create Table GroupMember (
GroupId int Not Null,
PersonId int Not Null,
CONSTRAINT FK_GroupMember_Group FOREIGN KEY (GroupId) References Group(GroupId),
CONSTRAINT FK_GroupMember_Person FOREIGN KEY (PersonId) References Person(PersonId),
CONSTRAINT PK_GroupMember PRIMARY KEY (GroupId, PersonID))
Джон Хартсок
источник
отличное объяснение: я думаю, что необходимость атрибутов для отношений m-to-n (в нормализованном стиле) является ключевым.
Wolf
может быть, добавлю немного пользы, объяснение было бы еще лучше
Martian2049
10

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

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

1234     Jobs
1234     Gates

Дополнительная литература: великие дебаты о первичных ключах или просто Google meaningless primary keysили даже внимательно изучите этот вопрос SO

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

Роберт Полсон
источник
1
1) ссылка "великие дебаты по первичному ключу" особенно глупа, информация корыстная и ложная. 2) Нельзя избежать индекса столбцов, которые делают строку уникальной. «Суррогатный» идентификатор с индексом всегда является дополнительным столбцом и дополнительным индексом. Скорее глупо, потому что это избыточно. И медленнее.
PerformanceDBA
2
«Великие дебаты о первичных ключах» не глупы. Это очень актуальная проблема для разработчиков, которые не являются разработчиками sql или администраторами баз данных sql и не проводят все свое время в sql. Даже в чистом sql я предпочел бы иметь бессмысленный автоматически сгенерированный ключ в качестве первичного ключа при присоединении, чем не забывать передавать n бит данных вокруг естественного ключа. Добро пожаловать на вашу точку зрения, но мы были бы признательны, если вы не будете так пренебрежительно относиться к вам.
Роберт Полсон
4

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

nvogel
источник
1
Что касается обеспечения уникального ключа, вы можете полагаться на комбинацию двух атрибутов, чтобы сформировать ключ, который логически не может быть продублирован, примером может служить человек и дата окончания из более крупного набора данных.
Джон Марк
3

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

ig0774
источник
3

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

HLGEM
источник
1
1) Производительность. Не в платформе SQL (возможно, в воображаемых sql и бесплатных программах). 2) Предпочтение не имеет значения. То, что таблицы требуют для целостности, имеет значение. 3) «Суррогатный» идентификатор с индексом всегда является дополнительным столбцом и дополнительным индексом. Так что на любой платформе это будет медленнее. Повторяя перформанс, вы сами себе противоречите. 4) Если вы не знаете , как обновить мифические «миллион детей записей в 215 дочерних таблицах» правильно задать вопрос.
PerformanceDBA
2
Я не согласен с утверждением: «Несколько столбцов в ключе в целом будут работать хуже, чем суррогатный ключ». Часто требуется дополнительный запрос, чтобы получить суррогатный ключ отношения, если вы его рассматриваете. В этот момент это полная дополнительная поездка в оба конца, которая снижает производительность.
ttugates
3

Ваш второй вопрос

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

зависит от реализации: он определен в реальной используемой СУБД. [1], [2], [3] Вам необходимо ознакомиться с технической спецификацией используемой вами системы баз данных. Некоторые из них очень подробны, некоторые нет. Поиск в Интернете таких ограничений может быть затруднен, поскольку терминология меняется. Термин составной первичный ключ должен быть обязательным;)

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


Волк
источник
2

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

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

Во второй таблице были «персонажи» - их имена и краткое описание. Первичный ключ был на charname.

Поскольку в каждом комиксе - за некоторыми исключениями - было несколько персонажей, и каждый персонаж появлялся в нескольких комиксах, было непрактично помещать столбец в «персонажи» или «комиксы», чтобы отразить это. Вместо этого я создал третью таблицу под названием «comicchars», и это был список того, какие персонажи появлялись в каких комиксах. Поскольку эта таблица по существу объединяла две таблицы, ей требовалось всего два столбца: charname и comicnum, и первичный ключ был на обоих.

Мистер начальный человек
источник
1

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

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

kiwicomb123
источник