2010-08-08 39 views
7

Tôi đang xây dựng một ứng dụng nhỏ và thiết lập các mối quan hệ khóa ngoài giữa các bảng. Tuy nhiên tôi đang bối rối là tại sao tôi thực sự cần điều này? Lợi thế là gì - nó có hỗ trợ tôi khi viết các truy vấn của tôi mà tôi không phải thực hiện bất kỳ phép nối nào không? Dưới đây là một đoạn mã ví dụ về cơ sở dữ liệu của tôi:Phím nước ngoài - Chúng làm gì cho tôi?

+-------------------+ 
| USERS    | 
+-------------------+ 
| user_id   | 
| username   | 
| create_date  | 
+-------------------+ 

+-------------------+ 
| PROJECTS   | 
+-------------------+ 
| project_id  | 
| creator   | 
| name    | 
| description  | 
+-------------------+ 

Có mối quan hệ chính giữa users. user_idprojects. creator

Tôi có thể thực hiện truy vấn như vậy không?

SELECT * FROM PROJECTS WHERE USERS.username = "a real user";

Vì MySQL nên biết mối quan hệ giữa các bảng? Nếu không thì chức năng thực sự của khóa ngoại trong thiết kế cơ sở dữ liệu là gì?

+0

Điều này có nên được di chuyển đến http://dba.stackexchange.com/? – simgineer

+0

Không, có thể là không. Nó đã được hỏi và trả lời trước khi trang web đó tồn tại. Không có lợi thế thực sự để di chuyển. –

Trả lời

16

Khóa nước ngoài cung cấp tính toàn vẹn tham chiếu. Dữ liệu trong cột khóa ngoài được xác thực - giá trị chỉ có thể là giá trị đã tồn tại trong cột & được xác định trong khóa ngoài. Nó rất hiệu quả trong việc ngăn chặn "dữ liệu xấu" - ai đó không thể nhập bất cứ thứ gì họ muốn - số, văn bản ASCII, v.v. Có nghĩa là dữ liệu được chuẩn hóa - giá trị lặp lại đã được xác định và tách biệt với bảng của riêng họ, về việc xử lý sự nhạy cảm với chữ trong văn bản ... và các giá trị là nhất quán. Điều này dẫn đến phần tiếp theo - các khóa ngoại là những gì bạn sử dụng để nối các bảng lại với nhau.

Truy vấn của bạn cho các dự án mà người dùng không hoạt động - bạn đang tham chiếu cột từ bảng USERS khi không có tham chiếu đến bảng trong truy vấn và không có truy vấn con nào được sử dụng để nhận thông tin đó trước khi liên kết nó tới bảng PROJECTS. Những gì bạn thực sự muốn sử dụng là:

SELECT p.* 
    FROM PROJECTS p 
    JOIN USERS u ON u.user_id = p.creator 
WHERE u.username = 'John Smith' 
+0

Cảm ơn bạn - Tôi đã hình dung rằng tôi có thể có được một cách từ Tham gia với điều này - nhưng bạn trả lời giúp mô tả chính xác những gì nó làm. –

0

Nếu mỗi người dùng thuộc về chính xác một dự án và mỗi dự án thuộc về một người dùng ngoại lệ thì người ta nói rằng các bảng có mối quan hệ 1-1 và có mối quan hệ khóa giữa users.user_id và projects.project_id là ok (mặc dù có lẽ không chuẩn).

Tuy nhiên, nếu người dùng có thể thuộc về nhiều dự án (hoặc dự án có thể có nhiều người dùng) thì bạn có mối quan hệ một đến nhiều và bạn cần có khóa ngoại.

Nếu dự án có thể có nhiều người dùng và người dùng có thể thuộc về nhiều dự án thì bạn có mối quan hệ nhiều đến nhiều và bạn cần một mô hình phức tạp hơn.

+0

Tôi đã thiết lập nhiều thiết kế cơ sở dữ liệu mà không cần tạo bất kỳ khóa ngoại nào và chúng đã sử dụng mối quan hệ một đến nhiều. Tôi muốn biết những gì các phím nước ngoài làm cho tôi mà tôi không thể làm mà không có chúng. –

+0

Với bố cục bảng của bạn ở trên, câu lệnh SQL của bạn sẽ làm gì để có được tất cả người dùng là một phần của project_id = 1? – EddieC

+1

@Marco Ceppi: Mặc dù bạn đã mô hình hóa các mối quan hệ mà không sử dụng khóa ngoại, không có gì ngăn người dùng nhập dữ liệu không liên quan đến (các) cột đại diện cho mối quan hệ đó. –

4

Về cơ bản, chúng sẽ không cung cấp cho bạn thêm chức năng nào. Chúng ngăn chặn bất kỳ chèn hoặc cập nhật nào vi phạm tính toàn vẹn tham chiếu của mô hình dữ liệu của bạn.

Một khía cạnh quan trọng khác trong quan điểm của tôi là họ truyền đạt mô hình dữ liệu tới bất kỳ nhà phát triển nào khác sử dụng nó. Tôi đã thường xuyên xem xét những gì các phím nước ngoài một bảng đã xem làm thế nào mô hình dữ liệu phù hợp với nhau trong nháy mắt.

+2

Tôi muốn nói xác thực dữ liệu là chức năng - ràng buộc khóa ngoài giống như ràng buộc CHECK trên steriod. Ràng buộc KIỂM TRA chỉ xác nhận dữ liệu; Khóa ngoài có nghĩa là bạn có thể thêm thông tin liên quan vào mối quan hệ đó - ngoài việc xác thực dữ liệu. –

3

Nếu bạn không bao giờ tham gia, bạn không cần khóa ngoại.

Nghĩ lại, nếu bạn không bao giờ tham gia, bạn không cần một cơ sở dữ liệu quan hệ! (ít đùa) Nghiêm túc, nếu bạn có nhiều hơn một bảng, bạn nên học cách sử dụng các phép nối, và cách thiết kế các khóa ngoại vào một lược đồ.

Như những người trả lời trước đó đã nói, các khóa ngoại thực thi tính toàn vẹn tham chiếu. Không có tính toàn vẹn tham chiếu, các phép nối tạo ra các kết quả bí ẩn.


Phản hồi trước đó của tôi không ghi nhận được câu hỏi thực sự đằng sau câu hỏi. Câu hỏi tôi trả lời là "tại sao có khóa ngoài trong lược đồ SQL", và câu trả lời là "để tham gia". Nhưng hãy đọc lại câu hỏi, tôi hiểu một câu hỏi tinh tế hơn nhiều, đó là "tại sao SQL không thể tham gia với tôi, nếu nó biết các liên kết". Đây là một câu hỏi thực sự tốt. Nó xứng đáng là một câu trả lời tốt hơn so với ở trên.

Ngôn ngữ nơi động cơ cung cấp điều kiện kết nối là có thể. Người ta chỉ cần nhìn vào công cụ thiết kế truy vấn đồ họa trong Microsoft Access. Khi một người đã khai báo tất cả các mối quan hệ intertable cho Access, người ta có thể lấy dữ liệu từ nhiều bảng mà không chỉ rõ các điều kiện kết nối lại. Access tự động tìm ra chúng.

Nếu người dùng tạo truy vấn hai bảng trong Access và sau đó chuyển sang chế độ xem SQL, người ta sẽ thấy rằng Access có hiệu lực đã tạo một kết hợp với điều kiện tham gia. Khả năng như vậy cũng có thể có trong các ngôn ngữ dựa trên ký tự, nhưng SQL không phải là một ngôn ngữ như vậy.

Tôi lưu ý rằng qua nhiều dự án có thể thuộc về một người dùng. Vì vậy, Người dùng là "bảng tham chiếu" trong lược đồ trên, chứ không phải là Dự án. Tôi hy vọng hướng điều hướng tự động dễ dàng hơn sẽ là tra cứu tự động từ bảng tham chiếu chứ không phải theo cách khác.

+0

Nhiều năm sau, tôi đã nhận thấy rằng nhiều người sử dụng thuật ngữ "khóa ngoại" để chỉ tham chiếu đến một cột có ràng buộc khóa ngoài được khai báo. Tôi không chắc liệu OP có nghĩa là điều đó không. Khi tôi học được công cụ này, nhiều năm trước, một khóa ngoại là chìa khoá ngoại, cho dù nó có được khai báo như vậy hay không. Các khóa nước ngoài không khai báo là lời mời phá vỡ tính toàn vẹn tham chiếu. Điều này làm lu mờ bất kỳ sự khác biệt hiệu suất nào có thể xảy ra. –

2

Sử dụng một ràng buộc khoá ngoại có thể cung cấp như sau:

  • Ngăn chặn các cơ sở dữ liệu chứa dữ liệu không phù hợp bằng cách ngăn chặn sai key
  • Ngăn chặn các cơ sở dữ liệu chứa dữ liệu không phù hợp bằng cách tự động xóa các hàng mồ côi (với ON DELETE CASCADE)
  • Cung cấp tài liệu cho các nhà phát triển trong tương lai mà cột là khóa ngoại mà

Tất nhiên nó không phải là ma cố gắng thực hiện bất kỳ điều nào trong số đó, nhưng có khả năng cải thiện chất lượng mã theo thời gian. Nghiêm ngặt về điều này thường là tốt - nó dẫn đến nhiều lỗi hơn trong thử nghiệm (và do đó ít hơn trong sản xuất)

Các vấn đề liên quan