ALTER TABLE для добавления составного первичного ключа

195

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

Как мне ALTER TABLE добавить составной первичный ключ для этой таблицы в MySQL с этими тремя столбцами?

David542
источник

Ответы:

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
@ Дэвид: это один первичный ключ, состоящий из нескольких полей, или составной ключ.
Марк Б.
3
@ David542 Конечно, вы можете - это составной первичный ключ, состоящий из 3 полей. Комбинация из 3 полей должна быть уникальной.
Адриан Корниш
2
спасибо за публикацию - действительно вытащил меня из борьбы с пользовательским интерфейсом
plditallo
1
один из самых ценных ответов в SO :)
alwbtc
21

@ Адриан Корниш ответ правильный. Тем не менее, есть еще одна оговорка для удаления существующего первичного ключа. Если этот первичный ключ используется в качестве внешнего ключа другой таблицей, вы получите сообщение об ошибке при попытке его удалить. В некоторых версиях 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 документы здесь для получения дополнительной информации.

cs_alumnus
источник
@All - Не могли бы вы поделиться эквивалентом JPA для того же?
Pra_A
17

Вы можете просто захотеть УНИКАЛЬНОЕ ОГРАНИЧЕНИЕ. Особенно, если у вас уже есть суррогатный ключ. (примером уже существующего суррогатного ключа будет один столбец, который является AUTO_INCREMENT)

Ниже приведен код SQL для уникального ограничения

ALTER TABLE `MyDatabase`.`Provider`
    ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing)
;
granadaCoder
источник
Спасибо, ограничение - это то, что я хотел, я не знал, о чем просить в этом первоначальном посте. Спасибо за добавление этого в поток.
ZaneDarken
Я обычно использую суррогатный ключ ...... затем добавляю уникальное ограничение. Таким образом… если «уникальность» изменится в будущем, отрегулировать ограничение не составит большого труда, чем возиться с первичным ключом. И если у вас есть дочерние таблицы, которые ссылаются на эту таблицу с помощью внешнего ключа, вам нужен только суррогатный ключ FK, а не все 3 столбца. -
granadaCoder
3
alter table table_name add primary key (col_name1, col_name2);
Навин Кумар Алонекар
источник
1

Определенно лучше использовать COMPOSITE UNIQUE KEY, как предложил @GranadaCoder, хотя и немного хитрый пример:

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

Артур Кушман
источник
0

ALTER TABLE table_name DROP PRIMARY KEY,ADD PRIMARY KEY (col_name1, col_name2);

Счастливый
источник