Зачем использовать несколько столбцов в качестве первичных ключей (составной первичный ключ) - PullRequest
98 голосов
/ 13 апреля 2010

Этот пример взят из 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. Это правильно?

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

Ответы [ 8 ]

110 голосов
/ 13 апреля 2010

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

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

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

23 голосов
/ 13 апреля 2010

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

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))
9 голосов
/ 15 апреля 2010

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

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

1234     Jobs
1234     Gates

Дополнительная литература: Великие дебаты по первичному ключу или просто Google meaningless primary keys или даже просмотр этого ТАКого вопроса

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

3 голосов
/ 23 ноября 2010

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

2 голосов
/ 19 января 2017

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

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

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

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


2 голосов
/ 22 ноября 2010

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

2 голосов
/ 13 апреля 2010

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

1 голос
/ 11 сентября 2016

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

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

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

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

...