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


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. Это верно?

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

... теперь есть ответ и на 2-й вопрос
— Wolf

1
@Martijn Peters. Почему был удален ответ?
— PerformanceDBA

Ответы:


119

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

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

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


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

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


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

3

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


3

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


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

2
Я не согласен с утверждением: «Несколько столбцов в ключе в целом будут работать хуже, чем суррогатный ключ». Часто требуется дополнительный запрос, чтобы получить суррогатный ключ отношения, если вы его рассматриваете. В этот момент это полная дополнительная поездка в оба конца, которая снижает производительность.
— ttugates

3

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

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

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

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



2

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

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

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

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


1

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.