Phân định cột / ràng buộc khóa ngoại
Giả sử bạn đang đề cập đến các ràng buộc khóa ngoại , câu trả lời ngắn gọn sẽ là bạn chỉ không sử dụng chúng .
Và đây là vấn đề dài:
Chúng tôi quen gọi cột là khóa ngoại sang các bảng khác. Đặc biệt là trong quá trình chuẩn hóa, các cụm từ như "user_purchase.i_id
là một khóa ngoại cho các items
bảng " sẽ rất phổ biến. Mặc dù đó là một cách hoàn toàn hợp lệ để mô tả mối quan hệ, nhưng nó có thể hơi mờ nhạt khi chúng ta đến giai đoạn triển khai.
Giả sử bạn đã tạo bảng của mình không có FOREIGN KEY
mệnh đề:
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
);
Lưu ý rằng, theo quan hệ, các cột khóa ngoại vẫn được triển khai . Có một cột tham chiếu đến user
bảng (id
) và một cái khác tham chiếu đến items
bảng (i_id
) - hãy đặt name
cột sang một bên trong giây lát. Hãy xem xét các dữ liệu sau:
user user_purchase items
| id username | | id i_id | | i_id name price |
| 23 john | | 55 10 | | 10 chocolate bar 3.42 |
| 55 mary | | 70 10 | | 33 mobile phone 82.11 |
| 70 fred | | 70 33 | | 54 toothpaste 8.67 |
| 55 10 | | 26 toy car 6.00 |
| 70 26 |
Mối quan hệ là ở đó. Nó được triển khai bằng user_purchase
bảng lưu trữ thông tin về ai đã mua những gì . Nếu chúng tôi truy vấn cơ sở dữ liệu để tìm một báo cáo có liên quan, chúng tôi sẽ thực hiện:
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
Và đó là cách chúng tôi sử dụng quan hệ và cột khóa ngoại có liên quan.
Bây giờ, điều gì sẽ xảy ra nếu chúng ta làm:
insert into user_purchase (id,i_id) values (23,99)
Rõ ràng, đây là một mục nhập không hợp lệ. Mặc dù có người dùng id=23
, không có mục nào có i_id=99
. RDBMS sẽ cho phép điều đó xảy ra, bởi vì nó không biết cách nào tốt hơn . Chưa.
Đó là nơi mà khóa ngoại ràng buộc nhập cuộc. Bằng cách chỉ định FOREIGN KEY (i_id) REFERENCES items(i_id)
trong user_purchase
định nghĩa bảng, về cơ bản chúng tôi cung cấp cho RDBMS một quy tắc để tuân theo: các mục nhập có i_id
các giá trị không có trong items.i_id
cột không được chấp nhận . Nói cách khác, trong khi một cột khóa ngoại triển khai tham chiếu , một khóa ngoại ràng buộc thực thi tính toàn vẹn của tham chiếu .
Tuy nhiên, lưu ý rằng select
ở trên sẽ không thay đổi, chỉ vì bạn đã xác định ràng buộc FK. Vì vậy, bạn không sử dụng các ràng buộc FK, RDBMS thực hiện, để bảo vệ dữ liệu của bạn.
Tiền thừa
Hãy tự hỏi bản thân:Tại sao bạn muốn điều đó? Nếu hai khóa ngoại phục vụ cùng một mục đích, thì việc dư thừa cuối cùng sẽ khiến bạn gặp rắc rối. Hãy xem xét các dữ liệu sau:
user_purchase items
| id i_id name | | i_id name price |
| 55 10 chocolate bar | | 10 chocolate bar 3.42 |
| 70 10 chocolate bar | | 33 mobile phone 82.11 |
| 70 33 mobile phone | | 54 toothpaste 8.67 |
| 55 10 toothpaste | | 26 toy car 6.00 |
| 70 26 toy car |
Chuyện gì với bức tranh vậy? Có phải người dùng 55
mua hai thanh sô cô la, hay một thanh sô cô la và kem đánh răng? Loại không rõ ràng này có thể dẫn đến rất nhiều nỗ lực để giữ cho dữ liệu được đồng bộ hóa, điều này sẽ không cần thiết nếu chúng ta chỉ giữ một trong các khóa ngoại. Trên thực tế, tại sao không bỏ name
hoàn toàn là cột, vì nó được ngụ ý bởi quan hệ.
Tất nhiên, chúng tôi có thể giải quyết vấn đề này bằng cách triển khai khóa ngoại tổng hợp, bằng cách đặt PRIMARY KEY(i_id,name)
cho các mục items
bảng (hoặc xác định thêm một UNIQUE(i_id,name)
lập chỉ mục, không thành vấn đề) và sau đó đặt FOREIGN KEY(i_id,name) REFERENCES items(i_id,name)
. Bằng cách này, chỉ các cặp (i_id, name) tồn tại trong các mục items
bảng sẽ hợp lệ cho user_purchases
. Ngoài thực tế là bạn vẫn sẽ có một khóa ngoại , cách tiếp cận này hoàn toàn không cần thiết, miễn là i_id
cột đã đủ để xác định một mục (không thể nói giống nhau cho name
cột ...).
Tuy nhiên, không có quy tắc nào chống lại việc sử dụng nhiều khóa ngoại cho một bảng. Trên thực tế, có những trường hợp đòi hỏi một cách tiếp cận như vậy. Xem xét một person(id,name)
bảng và parent(person,father,mother)
một, với dữ liệu sau:
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Rõ ràng, cả ba cột của parent
bảng là các khóa ngoại đối với person
. Không cho cùng một mối quan hệ , nhưng đối với ba cái khác nhau :Vì cha mẹ của một người cũng là một người, nên hai cột tương ứng phải tham chiếu đến cùng một bảng person
làm. Tuy nhiên, lưu ý rằng ba trường không chỉ có thể nhưng cũng có phải giới thiệu person
s trong cùng một parent
hàng, vì không ai là cha mẹ của chính mình và cha của không ai cũng là mẹ của anh ta.