Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Khóa ngoại MySQL

Khóa ngoại là một phần không thể thiếu trong việc tạo mối quan hệ trong cơ sở dữ liệu quan hệ. Đây là lý do và cách tạo chúng.

Vì vậy, chúng tôi đã thiết lập rằng khóa chính cung cấp một số nhận dạng duy nhất cho bảng. Nhưng khóa chính không phải là loại "khóa" duy nhất. Cơ sở dữ liệu của chúng tôi cũng có thể chứa các khóa ngoại.

Khoá ngoại là gì?

Một khóa ngoại là một cột (hoặc tập hợp các cột) trong một bảng xác định duy nhất một hàng của bảng khác. Điều này xác định mối quan hệ giữa hai bảng.

Khóa ngoại cho phép bạn tham chiếu chéo dữ liệu liên quan giữa các bảng. Điều này rất hữu ích khi một cột chứa dữ liệu được biểu diễn trong một bảng khác.

Ví dụ

Đây là sơ đồ về FruitShop của chúng tôi cơ sở dữ liệu hiển thị mối quan hệ giữa Fruit bảng và Đơn vị bàn.

Đường màu đen liên kết hai bảng biểu thị khóa ngoại. UnitId cánh đồng trên Fruit bảng là khóa ngoại của UnitId trường trên Đơn vị bàn. Do đó, giá trị mà chúng tôi chèn vào Fruit.UnitId phải tương ứng với một giá trị trong Units.UnitId . Điều này cho phép Fruit.UnitId để tham chiếu dữ liệu trong các cột khác cho bản ghi đó (tức là bản ghi có UnitId tương ứng ).

Dữ liệu

Vì vậy, nếu Trái cây của chúng tôi bảng chứa một bản ghi như sau:

FruitId FruitName Khoảng không quảng cáo UnitId DateEntered Ngày cập nhật
1 Apple 10 3 2012-11-27 12:42:10 2012-11-27 12:42:10

Đơn vị của chúng tôi bảng chứa các bản ghi sau:

UnitId Tên đơn vị DateEntered Ngày cập nhật
1 mảnh 2011-12-30 12:46:15 2011-12-30 12:46:15
2 Bunch 2011-12-30 12:46:15 2011-12-30 12:46:15
3 Kg 2011-12-30 12:46:15 2011-12-30 12:46:15
4 Vùng chứa 2011-12-30 12:46:15 2011-12-30 12:46:15
5 Bảng Anh 2011-12-30 12:46:15 2011-12-30 12:46:15
6 Ounce 2011-12-30 12:46:15 2011-12-30 12:46:15

Bạn có thể thấy rằng Fruit.UnitId trường chứa 3 . Bây giờ hãy nhìn vào Đơn vị bảng cho bản ghi có chứa 3 trong UnitId đồng ruộng. Bạn có thể thấy rằng bản ghi này đại diện cho Kilôgam . Do đó, bây giờ chúng ta biết rằng táo được đo bằng kg.

Ưu điểm của việc thiết lập cơ sở dữ liệu theo cách này là chúng ta không cần phải lặp lại "Kilôgam" cho mọi bản ghi sử dụng đơn vị đó. Giảm sự trùng lặp là một lợi ích chính của hệ quản trị cơ sở dữ liệu quan hệ.

Xem nhiều bản ghi trong Fruit bảng sẽ chia sẻ cùng một tên đơn vị (ví dụ:"Kilôgam", "Vùng chứa", "Bó", v.v.), chúng ta nên suy nghĩ kỹ trước khi thêm các bản sao vào cơ sở dữ liệu của mình. Không cần sử dụng mối quan hệ khóa ngoại, chúng ta chỉ có thể viết thẳng tên đơn vị vào Fruit bảng (và có thể gọi cột là "Unit", "UnitType" hoặc "UnitName"). Sau đó, chúng tôi sẽ kết thúc với nhiều bản ghi chia sẻ cùng một giá trị cho cột tên đơn vị. Chúng ta sẽ thấy "Kilôgam" được lặp đi lặp lại nhiều lần so với nhiều kỷ lục. Chúng tôi cũng sẽ thấy "Bunch" được lặp lại và bất kỳ loại đơn vị phổ biến nào khác.

Mặc dù không nhất thiết phải "sai" khi làm điều này, nhưng nói chung sẽ hiệu quả hơn nếu lưu trữ một bản ghi cho từng tên đơn vị đó trong một bảng riêng biệt, sau đó tham chiếu bảng đó qua UnitId cột. Làm điều này hiệu quả hơn là lặp đi lặp lại các tên đơn vị đó cho mọi bản ghi được tạo trong Fruits bàn. Nó cũng làm cho nó dễ dàng hơn nếu chúng tôi quyết định cập nhật tên đơn vị (ví dụ:thay đổi "Kilôgam" thành "Kilôgam"). Nếu chúng tôi cập nhật tên đơn vị, nó sẽ không ảnh hưởng đến Fruit bảng vì UnitId Sẽ vẫn như cũ. Ngoài ra, nó cũng giúp ngăn dữ liệu không nhất quán xuất hiện trong cơ sở dữ liệu của chúng tôi.

Ràng buộc khóa ngoài

Ràng buộc khóa ngoại là một đối tượng cơ sở dữ liệu hỗ trợ giữ cho dữ liệu khóa ngoại của bạn nhất quán. Bạn tạo một ràng buộc khóa ngoại để duy trì tính toàn vẹn của tham chiếu. Bằng cách tạo ràng buộc khóa ngoại, bạn đang yêu cầu MySQL thực thi các quy tắc nhất định đối với dữ liệu. Khi dữ liệu được chèn, xóa hoặc cập nhật, MySQL sẽ kiểm tra xem nó có tuân thủ khóa ngoại mà bạn đã tạo giữa các bảng hay không. Nếu không, nó sẽ ngăn dữ liệu được ghi / ghi đè / xóa, do đó duy trì tính toàn vẹn của tham chiếu.

Ví dụ:nếu người dùng cố gắng nhập giá trị UnitId vào Fruit.UnitId nhưng không có bản ghi tương ứng trong Units.UnitId thì MySQL sẽ ngăn người dùng nhập giá trị đó.

Khi chúng tôi tạo hai bảng của mình, chúng tôi đã thêm một ràng buộc khóa ngoại vào Fruit bàn. Đây là mã chúng tôi đã sử dụng để tạo ràng buộc:

CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE

Khi bạn mở rộng các nút ở SCHEMAS bên trái , bạn có thể thấy khóa ngoài mà chúng tôi đã tạo (cũng như các khóa chính):

Nếu bạn cố gắng chèn dữ liệu không tuân theo ràng buộc khóa ngoại, bạn sẽ gặp lỗi.

Ví dụ:nếu tôi cố gắng chèn một bản ghi vào Fruit bảng sử dụng UnitId giá trị không tồn tại trong Đơn vị bảng, tôi nhận được lỗi sau:

Điều này xảy ra vì tôi đang cố chèn giá trị 5 vào UnitId khi không có giá trị tương ứng trong Units.UnitId trường.

Để điều này thành công, tôi cần đảm bảo có một bản ghi trong Đơn vị bảng có UnitId trong tổng số 5 .

Khoá ngoại không hoạt động?

Đôi khi bạn có thể gặp phải trường hợp khóa ngoại dường như không hoạt động. Ví dụ:bạn có thể chèn thành công dữ liệu vào bảng mặc dù có khóa ngoại ngăn không cho dữ liệu đó vào.

Có một số điều bạn có thể kiểm tra trong tình huống này.

  • Đảm bảo bạn đã thêm ON DELETEON UPDATE các mệnh đề trong mã của bạn. Ví dụ:ON DELETE RESTRICT ON UPDATE CASCADE . Hãy xem ví dụ về TẠO BẢNG để biết thời điểm đặt mã này.
  • Đảm bảo bảng là InnoDB . Bạn có thể thực hiện việc này bằng cách thêm ENGINE=InnoDB ở cuối CREATE TABLE của bạn tuyên bố (xem ví dụ của tôi từ khi chúng tôi tạo bảng của mình). Một số công cụ (chẳng hạn như MyISAM ) không hỗ trợ ràng buộc khóa ngoại, nhưng chúng không đưa ra bất kỳ cảnh báo nào về điều này khi bạn cố gắng tạo ràng buộc khóa ngoại của mình. Nếu công cụ mặc định của bạn không phải là InnoDB thì có khả năng khóa ngoại của bạn sẽ không được hỗ trợ.
  • Đảm bảo MySQL đang thực sự kiểm tra các khóa ngoại. Bạn có thể thực hiện việc này bằng cách chạy mã sau:SET FOREIGN_KEY_CHECKS=1 .

Tắt tính năng kiểm tra khóa ngoài

Đôi khi các ràng buộc khóa ngoại có thể trở nên hạn chế một cách không cần thiết - đến mức chúng cản trở nghiêm trọng nỗ lực của bạn trong việc tải dữ liệu. Ví dụ, khi bạn vừa tạo cơ sở dữ liệu và bạn cần tải dữ liệu ban đầu. Hoặc nếu bạn cần xóa nhiều bảng và tải lại dữ liệu.

Nếu bạn không tải dữ liệu theo đúng thứ tự, có thể bạn sẽ tiếp tục gặp lỗi khóa ngoại do dữ liệu được tải không đúng thứ tự (tức là bạn đang cố tải các bảng con trước khi các bảng mẹ có đã tải dữ liệu).

Đây không chỉ là vấn đề khi tải dữ liệu. Bạn cũng có thể gặp sự cố này khi tạo cơ sở dữ liệu ngay từ đầu. Nếu bạn không tạo các bảng theo đúng thứ tự, bạn có thể gặp lỗi do bất kỳ ràng buộc khóa ngoại nào.

Nếu bạn không biết thứ tự cha-con chính xác, có thể mất rất nhiều thời gian và nỗ lực để thiết lập thứ tự chính xác để tạo cơ sở dữ liệu hoặc tải dữ liệu. Trong những trường hợp như thế này, tốt hơn hết bạn nên thông báo cho MySQL tạm thời không kiểm tra khóa ngoại vào lúc này.

Bạn có thể tắt tính năng kiểm tra khóa ngoại bằng mã sau:

FOREIGN_KEY_CHECKS=0

Để bật lại, hãy làm như sau:

FOREIGN_KEY_CHECKS=1

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Left Outer Join không trả về tất cả các hàng từ bảng bên trái của tôi?

  2. Nhập dữ liệu từ Bảng tính Excel hoặc CVS ​​vào MySQL

  3. Làm cách nào để ngăn chặn việc đưa SQL vào PHP?

  4. PHP PDO - Hàng số

  5. Tìm và thay thế toàn bộ cơ sở dữ liệu mysql