ALTER TABLE untuk menambahkan kunci primer komposit

195

Saya punya meja yang disebut provider. Saya memiliki tiga kolom disebut person, place, thing. Mungkin ada orang duplikat, tempat duplikat, dan barang-barang duplikat, tetapi tidak akan pernah ada kombinasi orang-tempat-benda duplikat.

Bagaimana saya ALTER TABLE untuk menambahkan kunci primer komposit untuk tabel ini di MySQL dengan tiga kolom ini?

David542
sumber

Jawaban:

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

Jika kunci utama sudah ada maka Anda ingin melakukan ini

ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing);
Adrian Cornish
sumber
17
@ David542 Tidak, tidak - Anda hanya dapat memiliki 1 kunci primer.
Adrian Cornish
35
@ David: ini adalah kunci primer tunggal yang terdiri dari beberapa bidang, alias kunci komposit.
Marc B
3
@ David542 Tentu saja Anda bisa - ini adalah kunci primer komposit yang terdiri dari 3 bidang. Kombinasi dari 3 bidang harus unik.
Adrian Cornish
2
terima kasih untuk posting - benar - benar membuat saya keluar dari berjuang dengan ui
plditallo
1
salah satu jawaban paling berharga di SO :)
alwbtc
21

@Adrian Cornish jawabannya benar. Namun, ada peringatan lain untuk menjatuhkan kunci primer yang ada. Jika kunci utama itu digunakan sebagai kunci asing oleh tabel lain, Anda akan mendapatkan kesalahan saat mencoba menjatuhkannya. Di beberapa versi mysql pesan kesalahan ada yang salah (per 5.5.17, pesan kesalahan ini masih

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

Jika Anda ingin menjatuhkan kunci utama yang direferensikan oleh tabel lain, Anda harus menjatuhkan kunci asing di tabel lain terlebih dahulu. Anda dapat membuat ulang kunci asing itu jika Anda masih menginginkannya setelah Anda membuat ulang kunci utama.

Juga, ketika menggunakan kunci komposit, urutan penting. Ini

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

bukan hal yang sama. Mereka berdua menegakkan keunikan pada set tiga bidang, namun dari sudut pandang pengindeksan ada perbedaan. Kolom diindeks dari kiri ke kanan. Misalnya, pertimbangkan pertanyaan berikut:

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 dapat menggunakan indeks kunci utama dalam pernyataan ALTER 1
A dapat menggunakan indeks kunci utama dalam pernyataan ALTER 2
C dapat menggunakan indeks
D tidak dapat menggunakan indeks baik

A menggunakan dua bidang pertama dalam indeks 2 sebagai indeks parsial. A tidak dapat menggunakan indeks 1 karena tidak tahu bagian tempat menengah dari indeks. Mungkin masih bisa menggunakan indeks parsial pada orang biasa saja.

D tidak dapat menggunakan indeks mana pun karena tidak mengenal orang.

Lihat dokumen mysql di sini untuk informasi lebih lanjut.

cs_alumnus
sumber
@ Semua - Bisakah Anda berbagi setara JPA untuk hal yang sama?
Pra_A
17

Anda mungkin hanya menginginkan KONSTRA UNIK. Apalagi jika Anda sudah memiliki kunci pengganti. (contoh kunci pengganti yang sudah ada akan menjadi satu kolom yang merupakan AUTO_INCREMENT)

Di bawah ini adalah kode sql untuk Batasan Unik

ALTER TABLE `MyDatabase`.`Provider`
    ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing)
;
granadaCoder
sumber
Terima kasih, kendala adalah apa yang saya inginkan, saya tidak tahu harus bertanya apa di posting awal ini. Terima kasih telah menambahkan ini ke utas.
ZaneDarken
Saya biasanya menggunakan kunci pengganti ...... lalu tambahkan batasan unik. Dengan cara ini .... jika "keunikan" berubah di jalan, itu tidak banyak drama untuk mengubah kendala, vs bermain-main dengan kunci utama. Dan jika Anda memiliki tabel anak yang merujuk kunci asing tabel ini, Anda hanya perlu FK kunci pengganti, tidak semua 3 kolom. -
granadaCoder
3
alter table table_name add primary key (col_name1, col_name2);
Naveen Kumar Alonekar
sumber
1

Pasti lebih baik menggunakan COMPOSITE UNIQUE KEY, seperti yang ditawarkan @GranadaCoder, contoh yang sedikit rumit:

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

Arthur Kushman
sumber
0

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

Beruntung
sumber