Як правильно створити складені первинні ключі - 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. Якби я це робив, який із них має найбільше значення?
(у цьому прикладі я поєдную ідентифікатор 11209 з ідентифікатором 437)

INT(9)11209437 (я можу уявити, чому це погано)
VARCHAR (10) 11209-437
DECIMAL (10,4)11209.437

Або щось інше?

Невже це буде добре використовувати це як Первинний ключ у БД MYSQL MYISAM?


Відповіді:


344

Я б використав складений (багатоколонний) ключ.

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

Таким чином, ви можете мати t1ID і t2ID як зовнішні ключі, що вказують і на їхні відповідні таблиці.


2
О, так ось ТИ як ти складеш складений ключ! схоже, я зовсім не розумію поняття. Дякую!! Тож щось подібне цілком для цілей індексації, а потім правильно? Оскільки я не зміг би посилатись на запис, використовуючи цей композит, мені все одно доведеться це робити UPDATE info ... WHERE t1ID=11209 AND t2ID=437?
Філіп

2
правильно. Хоча обидва стовпця повинні бути унікальними, де t1ID = 11209, ймовірно, буде достатньо.
AlexCuse

39
@AlexCuse комбінація обох стовпців унікальна, але для t1ID = 11209 може бути будь-яка кількість t2ID.
e18r

21

Я б не робив первинний ключ таблиці "інформація" складовим з двох значень з інших таблиць.

Інші можуть сформулювати причини краще, але відчуває себе неправильно мати стовпчик, який справді складається з двох відомостей. Що робити, якщо ви хочете чомусь відсортувати ідентифікатор з другої таблиці? Що робити, якщо ви хочете порахувати кількість присутніх значень з будь-якої таблиці?

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


1
Ви абсолютно праві щодо збереження чітких стовпців. Мені не було відомо, що ви можете мати унікальний індекс з двома стовпцями, і я думаю, що це насправді може бути хорошим варіантом для мене. Чи можу я запитати, чому ви все-таки вважаєте за краще зберігати Первинний ключ як автоматичне збільшення?
Філіп

3
У мене немає справді вагомих причин, і я визнаю, що це питання суперечок між мною та деякими моїми колегами, оскільки економічніше мати менше стовпців. Мені легше писати приєднання на одному іноземному ключі. Іноді значення цих таблиць "Зображення між двома таблицями" стає таким же важливим, як і оригінальні таблиці, а його первинний ключ стає стовпцем із зовнішнім ключем в інших таблицях.
wmorse

спасибі. Я думаю, що ваша приказка має багато сенсу, і я спробую це як унікальний індекс з двома стовпцями + первинний ключ з автоматичним збільшенням
Філіп

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, і навпаки. Тому створити поле для авточислення для Massachusetts CD-5 було б зайвим.

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

Тому, поки я не відповідаю на початкове запитання, я, безумовно, ціную пряму відповідь Адама.


4

Композиційні первинні ключі - це те, що ви хочете, коли ви хочете створити взаємозв'язок багато-багато з таблицею фактів. Наприклад, у вас може бути пакет оренди для відпустки, який включає в себе ряд властивостей. З іншого боку, власність також може бути доступною у складі ряду пакетів оренди як самостійно, так і з іншими властивостями. У цьому випадку ви встановлюєте взаємозв’язок між майном та орендною орендою з таблицею фактів властивості / пакету. Асоціація між властивістю та пакетом буде унікальною, ви завжди будете приєднуватися, використовуючи property_id разом із таблицею властивостей та / або package_id з таблицею пакетів. Кожне відношення є унікальним, а ключ автопосилення є зайвим, оскільки він не відображатиметься в будь-якій іншій таблиці. Отже, визначення складового ключа - відповідь.



1

@AlexCuse Я хотів додати це як коментар до вашої відповіді, але відмовився після декількох невдалих спроб додати нові рядки в коментарі.

Однак, t1ID є унікальним у table_1, але це не робить його унікальним і в таблиці INFO.

Наприклад:

У таблиці_1 є:
Поле Id
1 A
2 B

У таблиці_2 є:
Поле Id
1 X
2 Y

INFO тоді може мати:
t1ID t2ID поле
1 1 деякі
1 2 дані
2 1 у кожному
2 2 рядку

Тож у таблиці INFO для унікального визначення рядка вам потрібно як t1ID, так і t2ID


його називають складеним ключем
Павло П

1
@PavelP моя відповідь - коментар wrt Алекса "Хоча, оскільки обидва стовпці повинні бути унікальними, де t1ID = 11209, ймовірно, буде достатньо". ... Я погоджуюся, що використовувати складений ключ правильно, але для виявлення точної відповідності вам знадобляться і t1ID, і t2ID ... Я сподіваюся, що це зрозуміло вже зараз.
sactiw
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.