ZMIEŃ TABELĘ, aby dodać złożony klucz podstawowy

195

Mam stolik o nazwie provider. Mam trzy kolumny zwane person, place, thing. Mogą istnieć zduplikowane osoby, zduplikowane miejsca i zduplikowane rzeczy, ale nigdy nie może istnieć zduplikowana kombinacja osoba-miejsce-rzecz.

Jak mam ZMIENIĆ TABELĘ, aby dodać złożony klucz podstawowy dla tej tabeli w MySQL z tymi trzema kolumnami?

David542
źródło

Odpowiedzi:

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

Jeśli klucz podstawowy już istnieje, należy to zrobić

ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing);
Adrian Cornish
źródło
17
@ David542 Nie, nie ma - możesz mieć tylko 1 klucz podstawowy.
Adrian Cornish
35
@David: jest to jeden klucz podstawowy złożony z wielu pól, czyli klucz złożony.
Marc B
3
@ David542 Oczywiście, że możesz - to złożony klucz podstawowy składający się z 3 pól. Kombinacja 3 pól musi być unikalna.
Adrian Cornish
2
dzięki za wysłanie - naprawdę wyciągnąłem mnie z walki z interfejsem użytkownika
plditallo
1
jedna z najcenniejszych odpowiedzi w SO :)
alwbtc
21

Odpowiedź Adriana Cornisha jest poprawna. Istnieje jednak inne zastrzeżenie dotyczące upuszczania istniejącego klucza podstawowego. Jeśli ten klucz podstawowy jest używany jako klucz obcy w innej tabeli, podczas próby jego upuszczenia wystąpi błąd. W niektórych wersjach mysql komunikat o błędzie był zniekształcony (od 5.5.17 ten komunikat o błędzie jest nadal wyświetlany)

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

Jeśli chcesz upuścić klucz podstawowy, do którego odwołuje się inna tabela, najpierw musisz upuścić klucz obcy w tej drugiej tabeli. Możesz odtworzyć ten klucz obcy, jeśli nadal chcesz go po odtworzeniu klucza podstawowego.

Również w przypadku korzystania z kluczy kompozytowych ważna jest kolejność. Te

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

to nie to samo. Oba wymuszają unikalność na tym zestawie trzech pól, jednak z punktu widzenia indeksowania istnieje różnica. Pola są indeksowane od lewej do prawej. Rozważ na przykład następujące zapytania:

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 może używać indeksu klucza podstawowego w instrukcji ALTER 1
A może używać indeksu klucza podstawowego w instrukcji ALTER 2
C może używać dowolnego indeksu
D nie może używać żadnego indeksu

A wykorzystuje dwa pierwsze pola w indeksie 2 jako indeks częściowy. Nie można użyć indeksu 1, ponieważ nie zna części indeksu dotyczącej pośredniego miejsca. Jednak nadal może być w stanie użyć częściowego indeksu tylko dla osoby.

D nie może użyć żadnego z indeksów, ponieważ nie zna osoby.

Aby uzyskać więcej informacji, zobacz dokumentację mysql tutaj .

cs_alumnus
źródło
@Wszystko - czy możesz udostępnić ekwiwalent JPA dla tego samego?
Pra_A
17

Możesz po prostu WYJĄTKOWY OGRANICZENIE. Zwłaszcza jeśli masz już klucz zastępczy. (przykładem już istniejącego klucza zastępczego byłaby pojedyncza kolumna o wartości AUTO_INCREMENT)

Poniżej znajduje się kod SQL unikalnego ograniczenia

ALTER TABLE `MyDatabase`.`Provider`
    ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing)
;
granadaCoder
źródło
Dziękuję, ograniczenie było tym, czego chciałem, nie wiedziałem, o co prosić w tym początkowym poście. Dziękujemy za dodanie tego do wątku.
ZaneDarken,
Zwykle używam klucza zastępczego ......, a następnie dodaję unikalne ograniczenie. W ten sposób ... jeśli „wyjątkowość” zmieni się na późniejszym etapie, poprawienie ograniczenia nie jest niczym dramatycznym, a nie zadzieraniem z kluczem podstawowym. A jeśli masz tabele potomne, które odwołują się do klucza obcego do tej tabeli, musisz tylko użyć klucza zastępczego, a nie wszystkich 3 kolumn. -
granadaCoder,
3
alter table table_name add primary key (col_name1, col_name2);
Naveen Kumar Alonekar
źródło
1

Zdecydowanie lepiej jest użyć KOMPOZYTOWEGO UNIKALNEGO KLUCZA, jak oferował @GranadaCoder, choć jest to nieco trudny przykład:

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

Arthur Kushman
źródło
0

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

Szczęściarz
źródło