ALTER TABLE để thêm khóa chính tổng hợp


195

Tôi có một bảng gọi provider. Tôi có ba cột gọi là person, place, thing. Có thể có người trùng lặp, địa điểm trùng lặp và những thứ trùng lặp, nhưng không bao giờ có thể có sự kết hợp giữa người và địa điểm.

Làm thế nào tôi có thể THAY ĐỔI để thêm khóa chính tổng hợp cho bảng này trong MySQL với ba cột này?

Câu trả lời:


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

Nếu một khóa chính đã tồn tại thì bạn muốn làm điều này

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

17
@ David542 Không, không - bạn chỉ có thể có 1 khóa chính.
Adrian Cornish

35
@David: đó là một khóa chính duy nhất bao gồm nhiều trường, còn gọi là khóa tổng hợp.
Marc B

3
@ David542 Tất nhiên bạn có thể - đây là khóa chính tổng hợp bao gồm 3 trường. Sự kết hợp của 3 lĩnh vực phải là duy nhất.
Adrian Cornish

2
cảm ơn vì đã đăng bài - thực sự đã giúp tôi thoát khỏi trận chiến với ui
plditallo

1
một trong những câu trả lời quý giá nhất trong SO :)
alwbtc

21

Câu trả lời của @Adrian Cornish là chính xác. Tuy nhiên, có một cảnh báo khác để bỏ khóa chính hiện có. Nếu khóa chính đó đang được sử dụng làm khóa ngoại bởi một bảng khác, bạn sẽ gặp lỗi khi cố gắng thả nó. Trong một số phiên bản của mysql, thông báo lỗi không đúng định dạng (kể từ ngày 5.5.17, thông báo lỗi này vẫn còn

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

Nếu bạn muốn bỏ khóa chính được tham chiếu bởi một bảng khác, trước tiên bạn sẽ phải bỏ khóa ngoại trong bảng khác đó. Bạn có thể tạo lại khóa ngoại đó nếu bạn vẫn muốn nó sau khi bạn tạo lại khóa chính.

Ngoài ra, khi sử dụng các phím tổng hợp, thứ tự là rất quan trọng. Những

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

không phải là điều tương tự Cả hai đều thực thi tính duy nhất trên bộ ba trường đó, tuy nhiên từ quan điểm lập chỉ mục có một sự khác biệt. Các trường được lập chỉ mục từ trái sang phải. Ví dụ: xem xét các truy vấn sau:

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 có thể sử dụng chỉ mục khóa chính trong câu lệnh ALTER 1
A có thể sử dụng chỉ mục khóa chính trong câu lệnh ALTER 2
C có thể sử dụng chỉ mục
D không thể sử dụng một trong hai chỉ mục

A sử dụng hai trường đầu tiên trong chỉ mục 2 làm chỉ mục một phần. Không thể sử dụng chỉ mục 1 vì nó không biết phần vị trí trung gian của chỉ mục. Nó vẫn có thể sử dụng một chỉ mục một phần trên người.

Không thể sử dụng một trong hai chỉ số vì nó không biết người.

Xem các tài liệu mysql ở đây để biết thêm thông tin.


@ Tất cả - Bạn có thể vui lòng chia sẻ tương đương JPA không?
Pra_A

17

Bạn có thể chỉ đơn giản muốn một CONSTRAINT ĐỘC ĐÁO. Đặc biệt là nếu bạn đã có một chìa khóa thay thế. (ví dụ về khóa thay thế đã tồn tại sẽ là một cột duy nhất là AUTO_INCREMENT)

Dưới đây là mã sql cho một ràng buộc duy nhất

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

Cảm ơn bạn, một ràng buộc là những gì tôi muốn, tôi không biết phải hỏi gì trong bài viết ban đầu này. Cảm ơn đã thêm điều này vào chủ đề.
ZaneDarken

Tôi thường sử dụng khóa thay thế ...... sau đó thêm một ràng buộc duy nhất. Theo cách này .... nếu "tính duy nhất" thay đổi, thì sẽ không có nhiều kịch tính để điều chỉnh các ràng buộc, so với việc làm rối với khóa chính. Và nếu bạn có các bảng con mà khóa ngoài tham chiếu bảng này, bạn chỉ phải FK khóa thay thế, không phải cả 3 cột. -
granadaCoder


1

Chắc chắn sẽ tốt hơn khi sử dụng COMPOSITE UNIITE KEY, như @GranadaCoder đã cung cấp, một ví dụ khó khăn một chút:

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);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.