Как правильно создавать составные первичные ключи - MYSQL

182

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

table_1 (id, field)  
table_2 (id, field, field)
info ( ???, field)

Я пытаюсь решить, должен ли я сделать первичный ключ из infoнабора идентификаторов из table_1и table_2. Если бы я сделал это, какой из них имеет больше смысла?
(в этом примере я объединяю ID 11209 с ID 437)

INT(9)11209437 (я могу представить, почему это плохо)
VARCHAR (10) 11209-437
DECIMAL (10,4)11209.437

Или что-то другое?

Было бы хорошо использовать это в качестве первичного ключа в базе данных MYSQL MYISAM?

Filip
источник

Ответы:

343

Я бы использовал составной (многостолбцовый) ключ.

CREATE TABLE INFO (
    t1ID INT,
    t2ID INT,
    PRIMARY KEY (t1ID, t2ID)
) 

Таким образом, вы можете иметь t1ID и t2ID в качестве внешних ключей, указывая также на их соответствующие таблицы.

AlexCuse
источник
2
Ого, ТАК, как вы делаете составной ключ! Похоже, я полностью неправильно понял концепцию. Спасибо!! Значит, что-то подобное целиком предназначено для индексации, тогда правильно? Поскольку я не смог бы ссылаться на запись с помощью этого композита, мне все равно придется сделать это UPDATE info ... WHERE t1ID=11209 AND t2ID=437?
Filip
2
верный. Хотя, поскольку оба столбца должны быть уникальными, t1ID = 11209, вероятно, будет достаточно.
AlexCuse
39
@AlexCuse комбинация обоих столбцов уникальна, но для t1ID = 11209 может быть любое количество t2ID.
e18r
21

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

Другие могут лучше сформулировать причины, но неправильно иметь столбец, состоящий из двух частей информации. Что делать, если вы хотите по какой-то причине отсортировать по идентификатору из второй таблицы? Что если вы хотите посчитать, сколько раз значение из любой таблицы присутствует?

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

wmorse
источник
1
Вы абсолютно правы в отношении сохранения отдельных столбцов. Я не знал, что у вас может быть уникальный индекс из двух столбцов, и я думаю, что это может быть хорошим вариантом для меня. Могу ли я спросить, почему вы по-прежнему предпочитаете сохранять первичный ключ как автоинкремент?
Filip
3
У меня нет действительно веских причин, и я признаю, что это спор между мной и некоторыми моими коллегами, потому что более экономно иметь меньше колонок. Мне проще писать объединения на одном внешнем ключе. Иногда значение этих таблиц «Отображения между двумя таблицами» становится таким же важным, как и исходные таблицы, и их первичный ключ становится столбцом внешнего ключа в других таблицах.
wmorse
Спасибо. Я думаю, что ваше высказывание имеет много смысла, и я попробую это в качестве уникального индекса с двумя столбцами + первичного ключа с автоинкрементом
filip
1
Я думаю, что причина в моей голове в том, что вы хотите создать таблицу отношений. у вас есть три таблицы, скажем, рыночная площадь, валюта и провайдер, поставщик может существовать ТОЛЬКО на торговой площадке ОДИН РАЗ, поэтому ваша таблица отношений может содержать только одну валюту, поэтому вы будете составлять (id_market, id_provider), то есть вы можете только сделать что соединение один раз, попытка снова добавить один и тот же рынок и провайдера вместе, потерпит неудачу, что означает, что они уникальны, тогда у вас будет второй столбец, скажем, id_currency, означающий, что валюта единственная во всей таблице, имеет ли это смысл?
Кристофер Томас
1
Для тех, кто увидит эту ветку позже, обратите внимание, что причина в том, что это плохая практика, потому что она нарушает очень базовый принцип проектирования базы данных. 1-я нормальная форма требует, чтобы каждый фрагмент информации имел свой собственный столбец. Нет практически никаких причин нарушать это и множество преимуществ нормализации структуры вашей базы данных.
smcjones
15

синтаксис, CONSTRAINT constraint_name PRIMARY KEY(col1,col2,col3)например:

CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

приведенный выше пример будет работать, если вы пишете его во время создания таблицы, например:

CREATE TABLE person (
   P_Id int ,
   ............,
   ............,
   CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
);

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

ALTER TABLE table_name ADD CONSTRAINT constraint_name PRIMARY KEY (P_Id,LastName)
Ритабрата Гаутам
источник
8

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

alter table employee add primary key(emp_id,emp_name);
Усман Якуб
источник
5

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

Например, в каждом штате США есть набор уникальных округов Конгресса. Хотя во многих штатах CD-5 может быть отдельно, в любом из 50 штатов никогда не будет более одного CD-5, и наоборот. Поэтому создание поля автонумерации для Массачусетса CD-5 было бы излишним.

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

Поэтому, хотя я не отвечаю на первоначальный вопрос, я, безусловно, ценю прямой ответ Адама.

KiloVoltaire
источник
4

Составные первичные ключи - это то, что вам нужно, когда вы хотите создать связь «многие ко многим» с таблицей фактов. Например, у вас может быть пакет аренды на время отпуска, который включает в себя ряд свойств. С другой стороны, недвижимость также может быть доступна как часть ряда пакетов аренды, либо самостоятельно, либо вместе с другими объектами. В этом сценарии вы устанавливаете связь между свойством и пакетом аренды с помощью таблицы фактов свойства / пакета. Связь между свойством и пакетом будет уникальной, вы можете присоединиться только с помощью property_id с таблицей свойств и / или package_id с таблицей пакетов. Каждое отношение уникально, и ключ auto_increment является избыточным, поскольку он не будет отображаться ни в одной другой таблице. Следовательно, определение составного ключа является ответом.

Адам Пенни
источник
1
CREATE  TABLE `mom`.`sec_subsection` (

  `idsec_sub` INT(11) NOT NULL ,

  `idSubSections` INT(11) NOT NULL ,

  PRIMARY KEY (`idsec_sub`, `idSubSections`) 

);
Мастер Разума
источник
1

@AlexCuse Я хотел добавить это как комментарий к вашему ответу, но сдался после нескольких неудачных попыток добавить новые строки в комментарии.

Тем не менее, t1ID уникален в table_1, но это не делает его уникальным и в таблице INFO.

Например:

Таблица_1 содержит:
Id Поле
1 A
2 B

Таблица_2 имеет:
Id Поле
1 X
2 Y

ИНФО затем может иметь:
t1ID t2ID поле
1 1 какой-то
1 2 данных
2 1 в каждой
2 2 строке

Таким образом, в таблице INFO для уникальной идентификации строки вам нужны и t1ID, и t2ID.

sactiw
источник
его называют составным ключом
Павел Ф
1
@PavelP мой ответ на комментарий Алекса «Хотя оба столбца должны быть уникальными, t1ID = 11209, вероятно, будет достаточно». ... Я согласен, что использование составного ключа - это правильно, но для точного определения соответствия вам понадобятся и t1ID, и t2ID ... Надеюсь, теперь это понятно.
Сакхив