ALTER TABLE, щоб додати складений первинний ключ


195

У мене називається таблиця provider. У мене є три колонки під назвою person, place, thing. Тут можуть бути дублікати осіб, дублікати місць і копії речей, але ніколи не може бути поєднання дублікату людина-місце-річ.

Як я можу ПІСЛЯ ТАБЛИЦІ додати складений первинний ключ для цієї таблиці в MySQL з цими трьома колонками?

Відповіді:


426
ALTER TABLE provider ADD PRIMARY KEY(person,place,thing);

Якщо первинний ключ вже існує, ви хочете це зробити

ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing);

17
@ David542 Ні, це не так - у вас може бути лише 1 первинний ключ.
Адріан Корніш

35
@David: це єдиний первинний ключ, що складається з декількох полів, також складений ключ.
Марк Б

3
@ David542 Звичайно, можна - це складений первинний ключ, що складається з 3-х полів. Поєднання трьох полів повинно бути унікальним.
Адріан Корніш

2
спасибі за публікацію - насправді
визволив

1
одна з найцінніших відповідей в SO :)
alwbtc

21

@Adrian Cornish відповідь правильна. Однак є ще один застереження щодо скидання існуючого первинного ключа. Якщо цей первинний ключ використовується в якості іноземного ключа в іншій таблиці, ви отримаєте помилку при спробі скинути його. У деяких версіях mysql повідомлення про помилку було неправильно сформовано (станом на 5.5.17 це повідомлення про помилку все ще є)

alter table parent  drop column id;
ERROR 1025 (HY000): Error on rename of
'./test/#sql-a04_b' to './test/parent' (errno: 150).

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

Також при використанні складових ключів важливий порядок. Ці

1) ALTER TABLE provider ADD PRIMARY KEY(person,place,thing);
and
2) ALTER TABLE provider ADD PRIMARY KEY(person,thing,place);

не одне й те саме. Вони обидва забезпечують унікальність на наборі з трьох полів, однак з точки зору індексування є різниця. Поля індексуються зліва направо. Наприклад, розгляньте такі запити:

A) SELECT person, place, thing FROM provider WHERE person = 'foo' AND thing = 'bar';
B) SELECT person, place, thing FROM provider WHERE person = 'foo' AND place = 'baz';
C) SELECT person, place, thing FROM provider WHERE person = 'foo' AND place = 'baz' AND thing = 'bar';
D) SELECT person, place, thing FROM provider WHERE place = 'baz' AND thing = 'bar';

B може використовувати індекс первинного ключа в операторі ALTER 1
A може використовувати індекс первинного ключа в операторі ALTER 2
C може використовувати будь-який індекс
D не може використовувати жоден індекс

A використовує перші два поля в індексі 2 як частковий індекс. Індекс 1 не може використовувати, оскільки він не знає проміжну частину індексу. Можливо, все-таки вдасться використовувати частковий індекс лише для людини.

Не можу використовувати жоден індекс, тому що він не знає людину.

Дивіться документи mysql тут для отримання додаткової інформації.


@All - Чи можете ви поділитися еквівалентом JPA за те саме?
Pra_A

17

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

Нижче наведено код sql для унікального обмеження

ALTER TABLE `MyDatabase`.`Provider`
    ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing)
;

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

Зазвичай я використовую сурогатний ключ ...... потім додаю унікальне обмеження. Таким чином .... якщо "унікальність" зміниться в дорозі, не дуже драматично налаштовувати обмеження, проти возитися з первинним ключем. І якщо у вас є дочірні таблиці, на які посилається ця таблиця із зарубіжними ключами, вам потрібно лише FK сурогатний ключ, а не всі 3 стовпці. -
granadaCoder


1

Однозначно краще використовувати КОМПОЗИТНИЙ УНІКАЛЬНИЙ КЛЮЧ, як запропонував @GranadaCoder, хоч трохи складний приклад:

ALTER IGNORE TABLE table_name ADD UNIQUES INDEX idx_name(some_id, another_id, one_more_id);


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.