Cách tạo khóa chính tổng hợp - MYSQL


182

Đây là một sự đơn giản hóa quá mức của một thiết lập mãnh liệt mà tôi đang làm việc. table_1table_2cả hai đều có các khóa chính thay thế tự động làm ID. infolà một bảng chứa thông tin về cả hai table_1table_2.

table_1 (id, field)  
table_2 (id, field, field)
info ( ???, field)

Tôi đang cố gắng quyết định xem tôi có nên tạo khóa chính của infohỗn hợp ID từ table_1table_2. Nếu tôi làm điều này, cái nào trong số này có ý nghĩa nhất?
(trong ví dụ này tôi đang kết hợp ID 11209 với ID 437)

INT(9)11209437 (tôi có thể tưởng tượng tại sao điều này là xấu)
VARCHAR (10) 11209-437
DECIMAL (10,4)11209.437

Hay cái gì khác?

Điều này có ổn không khi sử dụng nó làm Khóa chính trên DB MYSQL MYISAM?


Bản sao có thể có của Khóa chính nhiều cột trong MySQL 5
dotancohen

Câu trả lời:


343

Tôi sẽ sử dụng một phím tổng hợp (nhiều cột).

CREATE TABLE INFO (
    t1ID INT,
    t2ID INT,
    PRIMARY KEY (t1ID, t2ID)
) 

Bằng cách này, bạn cũng có thể có t1ID và t2ID làm các khóa ngoại trỏ vào các bảng tương ứng của chúng.


2
Oh wow vậy đó là cách bạn tạo một khóa tổng hợp! Có vẻ như tôi đã hoàn toàn hiểu sai về khái niệm này. Cảm ơn bạn!! Vì vậy, một cái gì đó như thế này là hoàn toàn cho mục đích lập chỉ mục sau đó chính xác? Như trong tôi sẽ không thể tham chiếu một bản ghi bằng cách sử dụng hỗn hợp này, tôi vẫn sẽ phải làm như vậy UPDATE info ... WHERE t1ID=11209 AND t2ID=437?
filip

2
chính xác. Mặc dù cả hai cột phải là duy nhất, trong đó t1ID = 11209 có thể là đủ.
AlexCuse

39
@AlexCuse sự kết hợp của cả hai cột là duy nhất, nhưng với t1ID = 11209, có thể có bất kỳ số lượng t2ID nào.
e18r

21

Tôi sẽ không biến khóa chính của bảng "thông tin" thành tổng hợp của hai giá trị từ các bảng khác.

Những người khác có thể nói rõ lý do tốt hơn, nhưng cảm thấy sai khi có một cột thực sự được tạo thành từ hai mẩu thông tin. Điều gì nếu bạn muốn sắp xếp ID từ bảng thứ hai vì một số lý do? Điều gì xảy ra nếu bạn muốn đếm số lần một giá trị từ một trong hai bảng có mặt?

Tôi sẽ luôn giữ chúng như hai cột riêng biệt. Bạn có thể sử dụng khóa gốc hai cột trong mysql ... PRIMARY KEY (id_a, id_b) ... nhưng tôi thích sử dụng chỉ mục duy nhất hai cột và có trường khóa chính tăng tự động.


1
Bạn hoàn toàn đúng về việc giữ các cột riêng biệt. Tôi đã không biết rằng bạn có thể có chỉ mục duy nhất hai cột và tôi nghĩ rằng đó thực sự có thể là một lựa chọn tốt cho tôi. Tôi có thể hỏi mặc dù tại sao bạn vẫn muốn giữ Khóa chính là tự động tăng không?
filip

3
Tôi không có lý do thực sự thuyết phục và tôi thừa nhận đây là một điểm bất đồng giữa tôi và một số đồng nghiệp của mình, vì sẽ tiết kiệm hơn khi có ít cột hơn. Tôi thấy dễ dàng hơn khi viết các phép nối trên một khóa ngoại duy nhất. Đôi khi, tầm quan trọng của các bảng này "Ánh xạ giữa hai bảng" trở nên quan trọng như các bảng gốc và khóa chính của nó trở thành một cột khóa ngoại trong các bảng khác.
wmorse

cảm ơn bạn. Tôi nghĩ những gì bạn nói có ý nghĩa và tôi sẽ thử nó như một chỉ mục duy nhất hai cột + khóa chính tăng tự động
filip

1
Tôi đoán một lý do từ đỉnh đầu của tôi là bạn muốn tạo một bảng mối quan hệ. bạn có ba bảng, ví dụ như thị trường, tiền tệ và nhà cung cấp, nhà cung cấp CHỈ có thể tồn tại trong thị trường ONCE, do đó bảng mối quan hệ của bạn chỉ có thể cung cấp một loại tiền tệ, do đó, bạn sẽ kết hợp (id_market, id_provider) nghĩa là bạn chỉ có thể thực hiện kết nối đó một lần, cố gắng thêm lại cùng một thị trường và nhà cung cấp sẽ thất bại, nghĩa là chúng là duy nhất, sau đó bạn có một cột thứ hai, nói id_currency, có nghĩa là tiền tệ là số ít trong toàn bộ bảng, điều đó có hợp lý không?
Christopher Thomas

1
Đối với bất kỳ ai nhìn thấy chủ đề này sau này, xin lưu ý rằng lý do đây là thực tiễn xấu là vì nó vi phạm một nguyên tắc rất cơ bản của thiết kế cơ sở dữ liệu. Mẫu thông thường thứ 1 yêu cầu mọi thông tin đều có cột riêng. Hầu như không có lý do để vi phạm điều này và nhiều lợi ích để bình thường hóa cấu trúc cơ sở dữ liệu của bạn.
smcjones

15

cú pháp là CONSTRAINT constraint_name PRIMARY KEY(col1,col2,col3)ví dụ ::

CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

ví dụ trên sẽ hoạt động nếu bạn đang viết nó trong khi bạn đang tạo bảng chẳng hạn ::

CREATE TABLE person (
   P_Id int ,
   ............,
   ............,
   CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
);

để thêm ràng buộc này vào một bảng hiện có, bạn cần tuân theo cú pháp sau

ALTER TABLE table_name ADD CONSTRAINT constraint_name PRIMARY KEY (P_Id,LastName)

8

Giả sử bạn đã tạo một bảng bây giờ, bạn có thể sử dụng truy vấn này để tạo khóa chính tổng hợp

alter table employee add primary key(emp_id,emp_name);

5

Ngoài sở thích thiết kế cá nhân, có những trường hợp người ta muốn sử dụng các khóa chính tổng hợp. Các bảng có thể có hai hoặc nhiều trường cung cấp một kết hợp duy nhất và không nhất thiết phải bằng các khóa ngoại.

Ví dụ, mỗi tiểu bang Hoa Kỳ có một tập hợp các quận của Quốc hội. Mặc dù nhiều tiểu bang có thể có CD-5 riêng lẻ, nhưng sẽ không bao giờ có nhiều hơn một CD-5 ở bất kỳ trong số 50 tiểu bang và ngược lại. Do đó, việc tạo trường số tự động cho Massachusetts CD-5 sẽ là dư thừa.

Nếu cơ sở dữ liệu điều khiển một trang web động, việc viết mã để truy vấn trên tổ hợp hai trường có thể đơn giản hơn nhiều so với trích xuất / gửi lại khóa tự động đánh số.

Vì vậy, trong khi tôi không trả lời câu hỏi ban đầu, tôi chắc chắn đánh giá cao câu trả lời trực tiếp của Adam.


4

Các khóa chính tổng hợp là những gì bạn muốn nơi bạn muốn tạo mối quan hệ nhiều đến nhiều với một bảng thực tế. Ví dụ: bạn có thể có một gói cho thuê kỳ nghỉ bao gồm một số tài sản trong đó. Mặt khác, tài sản cũng có thể có sẵn như là một phần của một số gói cho thuê, một mình hoặc với các tài sản khác. Trong trường hợp này, bạn thiết lập mối quan hệ giữa tài sản và gói cho thuê với bảng thực tế thuộc tính / gói. Sự kết hợp giữa một thuộc tính và một gói sẽ là duy nhất, bạn sẽ chỉ tham gia bằng property_id với bảng thuộc tính và / hoặc pack_id với bảng gói. Mỗi mối quan hệ là duy nhất và khóa auto_increment là không cần thiết vì nó sẽ không có trong bất kỳ bảng nào khác. Do đó xác định khóa tổng hợp là câu trả lời.


1
CREATE  TABLE `mom`.`sec_subsection` (

  `idsec_sub` INT(11) NOT NULL ,

  `idSubSections` INT(11) NOT NULL ,

  PRIMARY KEY (`idsec_sub`, `idSubSections`) 

);

1

@AlexCuse Tôi muốn thêm điều này dưới dạng nhận xét vào câu trả lời của bạn nhưng đã bỏ cuộc sau khi thực hiện nhiều lần thất bại để thêm dòng mới trong nhận xét.

Điều đó nói rằng, t1ID là duy nhất trong bảng_1 nhưng điều đó cũng không làm cho nó trở nên duy nhất trong bảng INFO.

Ví dụ:

Bảng_1 có:
Trường Id
1 A
2 B

Bảng_2 có:
Trường Id
1 X
2 Y

INFO sau đó có thể có:
t1ID t2ID trường
1 1 một số
1 2 dữ liệu
2 1 trong mỗi
2 2 hàng

Vì vậy, trong bảng INFO để xác định duy nhất một hàng bạn cần cả t1ID và t2ID


nó được gọi là khóa tổng hợp
Pavel P

1
@PavelP câu trả lời của tôi là viết bình luận của Alex "Mặc dù cả hai cột phải là duy nhất, trong đó t1ID = 11209 có thể là đủ." ... Tôi đồng ý rằng sử dụng khóa tổng hợp là chính xác nhưng để xác định khớp chính xác, bạn sẽ cần cả t1ID và t2ID ... Tôi hy vọng nó đã rõ ràng ngay bây giờ.
sactiw
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.