Nó có được coi là một thực tiễn xấu khi có nhiều FK không thể hủy trên một bảng trong SQL Server


13

Trên cấu trúc cơ sở dữ liệu của tôi trong SQL Server, tôi có 3 loại sản phẩm yêu cầu thông tin khác nhau về đơn hàng. Vì vậy, tôi đã tạo ra một Customersbảng và ba đơn đặt hàng các bảng khác nhau: OrdersForProductAs, OrdersForProductBs, OrdersForProductCs. Tất cả các bảng đơn đặt hàng có một đến nhiều mối quan hệ trên Customersbàn.

Tôi cũng có một bảng khác đang Paymentsvà sẽ giữ các chi tiết thanh toán bên trong. Nhưng tôi có nghi ngờ ở đây về cách cấu trúc nó.

Vì tôi có nhiều loại sản phẩm và một khách hàng có thể có đơn đặt hàng cho nhiều sản phẩm cùng một lúc, tôi cần liên kết ba bảng đơn hàng đó với Paymentsbảng.

Vấn đề khác là khách hàng có thể chỉ có một đơn đặt hàng cho một loại sản phẩm. Vì vậy, các cột FK trên Paymentsbảng cần phải có nullable.

Câu hỏi của tôi là liệu những nullablecột FK đó có làm tôi đau đầu về lâu dài hay không? Nói chung, nó có được coi là một thực tiễn xấu khi có các cột FK không thể bỏ qua trên một bảng không?


2
Đảm bảo bạn bao gồm một ràng buộc kiểm tra để ít nhất một trong số các FK đó không có giá trị.
Damien_The_Unbeliever

3
Một khóa ngoại không thể là một quá nhiều.
nvogel

Câu trả lời:


13

Tôi muốn hỏi tại sao bạn có OrdersForProductXtất cả các bảng
Có thể vấn đề FK mà bạn đã hỏi có thể được thiết kế ...

Nếu các bảng này có cùng cấu trúc, thì bạn chỉ cần một ProductTypecột trên một số OrderProductbảng. Sau đó, Paymentchỉ cần liên kết đến đó với một FK

Nếu bảng có cấu trúc khác nhau, tôi giả sử chúng có một số thuộc tính chung. Vì vậy, bạn có thể có một OrderProductbảng chung sau đó là bảng con cụ thể cho mỗi loại sản phẩm (xem bên dưới) Một lần nữa, Paymentchỉ cần liên kết đến bảng commone với một FK

Đây là "mô hình superkey / subtype"

  • UQ1 là "siêu khóa" được sử dụng một khóa ngoại trên các bảng phụ
  • Mỗi bảng phụ có PK và FK tổng hợp trên (OrderID, ProductType)
  • Mỗi bảng phụ có ràng buộc KIỂM TRA để hạn chế các loại trong bảng đó

Đặt hàng sản phẩm

  • Đặt hàngID, PK, UQ1
  • Loại sản phẩm, UQ1
  • Thông thường1
  • ...

Đặt hàng sản phẩmA

  • Đặt hàng, PK, FK
  • ProductType, PK, FK, KIỂM TRA ProductType = A
  • Sản phẩm1
  • ...

Đặt hàng sản phẩm

  • Đặt hàng, PK, FK
  • ProductType, PK, FK, KIỂM TRA ProductType = B
  • ProductBT Breath1
  • ...

4
@tugberk: Lưu ý rằng bạn sẽ không có NULLcột FK với phương pháp này.
ypercubeᵀᴹ

"Nếu các bảng này có cùng cấu trúc" Chúng không có cùng cấu trúc.
tugberk

5

Tránh "khóa ngoại" vô giá trị. Họ có nhiều nhược điểm.

Ràng buộc trên một hàng tham chiếu không phải lúc nào cũng được thực thi khi khóa ngoại chứa null. Tuy nhiên, hành vi mặc định đó không nhất quán giữa các DBMS khác nhau. Một số DBMS hỗ trợ các tùy chọn cấu hình để thay đổi hành vi của các khóa ngoại không thể và một số thì không. Do đó, các nhà phát triển và người dùng SQL có thể không rõ ràng về những gì ràng buộc khóa ngoại không thể thực sự có nghĩa là gì từ góc độ toàn vẹn dữ liệu. Chuyển cơ sở dữ liệu giữa các sản phẩm DBMS hoặc thậm chí giữa các máy chủ khác nhau sử dụng cùng một sản phẩm có thể cho kết quả không nhất quán.

Các công cụ thiết kế cơ sở dữ liệu, công cụ tích hợp và phần mềm khác không phải lúc nào cũng hỗ trợ chúng một cách chính xác và kết quả chúng tạo ra có thể sai.

Khóa ngoại thường được sử dụng trong các phép nối và logic truy vấn khác, kết hợp các vấn đề cho người dùng nghĩ rằng ràng buộc có hiệu lực khi không hoặc ai không biết logic được áp dụng bởi DBMS cụ thể của bạn.

Một số tính năng tối ưu hóa truy vấn cho phép viết lại truy vấn và các tối ưu hóa khác có thể không khả dụng khi khóa ngoại không thể thực hiện được.

Theo thuật ngữ logic, một ràng buộc "khóa ngoại" không thể thực hiện được có ý nghĩa logic nhiều. Theo tiêu chuẩn SQL, một ràng buộc như vậy có thể không bị vi phạm ngay cả khi bảng được tham chiếu trống. Điều đó mâu thuẫn với một trong những biện minh được cho là phổ biến nhất khi sử dụng null - rằng nó đại diện cho trường hợp "không xác định". Nếu không có giá trị hợp lệ của X thì bất kỳ X "không xác định" nào chắc chắn không thể là giá trị hợp lệ - và SQL sẽ cho phép nó.

Khóa ngoại không thể hoàn toàn không cần thiết. Bạn luôn có thể phân tách khóa ngoại sang bảng mới hoặc sử dụng mẫu siêu kiểu / kiểu phụ để không cần null. Vì lợi ích của sự đơn giản và chính xác, do đó tốt hơn hết là bỏ null hơn là đặt chúng vào.


2

Tôi chưa bao giờ nghe thấy nó được coi là thực hành xấu để sử dụng các cột FK không thể. Chúng phù hợp lý tưởng cho một cột tham chiếu một bảng khác nhưng có thể không được điền vào (tức là dữ liệu tùy chọn).

(Tại sao bạn nghĩ nó sẽ là một vấn đề?)


Cảm ơn! Chà, tôi không chắc lắm về điều đó nhưng tôi đã có một dự án như thế vài năm trước và tôi nhớ rằng tôi đang đau đầu về điều gì đó . Vì vậy, tôi không rõ ràng như bạn thấy: đó là lý do tại sao tôi hỏi câu hỏi.
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.