Thiết kế cơ sở dữ liệu: Hai 1 đến nhiều mối quan hệ cho cùng một bảng


20

Tôi phải lập mô hình tình huống trong đó tôi có bảng Chequing_Account (chứa ngân sách, số iban và các chi tiết khác của tài khoản) có liên quan đến hai bảng khác nhau Person và Corporation có thể có 0, 1 hoặc nhiều tài khoản đếm tiền.

Nói cách khác, tôi có hai mối quan hệ 1-nhiều với cùng một tài khoản Chequing

Tôi muốn nghe giải pháp cho vấn đề này tôn trọng các yêu cầu chuẩn hóa. Hầu hết các giải pháp tôi đã nghe xung quanh là:

1) tìm một thực thể chung mà cả Person và Corporation thuộc và tạo một bảng liên kết giữa bảng này và bảng Chequing_Account, điều này là không thể trong trường hợp của tôi và ngay cả khi tôi muốn giải quyết vấn đề chung và không phải là trường hợp cụ thể này.

2) Tạo hai bảng liên kết PersonToChequingAccount và CorporationToChequingAccount có liên quan đến hai thực thể với Tài khoản Chequing. Tuy nhiên, tôi không muốn hai Người có cùng một tài khoản đếm tiền và tôi không muốn có một người tự nhiên và một Công ty để chia sẻ một tài khoản đếm tiền! xem hình ảnh này

http://i41.tinypic.com/35i6kbk.png

3) Tạo hai khóa ngoại trong Tài khoản Chequing trỏ đến Công ty và Người tự nhiên, tuy nhiên tôi sẽ thực thi rằng một Người và Công ty có thể có nhiều tài khoản đếm tiền, tuy nhiên tôi sẽ phải đảm bảo rằng mỗi hàng ChequingAccount không phải là cả hai mối quan hệ Công ty và người tự nhiên vì tài khoản checquing là của một công ty hoặc của một thể nhân. xem hình ảnh này

http://i40.tinypic.com/1rpv9z.png

Có giải pháp nào sạch hơn cho vấn đề này không?


Bạn đã nghĩ về việc có ví dụ như OwnerTypeIDtrong ChecquingAccountbảng, với 1=Corporation2=NaturalPerson? Bằng cách đó, bạn chỉ cần một OwnerIDtrong ChecquingAccountbảng, mà bạn có thể lập chỉ mục cùng với OwnerTypeID.
RoKa

Tôi không chỉ cần biết đó là tập đoàn hay thể nhân mà còn phải biết id tương ứng, vì vậy tôi cần một số id và không chỉ là giá trị 1 hoặc 2! Giải pháp 3 là những gì tôi tìm thấy ở đây Tôi có hai cột có id cho tập đoàn hoặc thể nhân
dendini

2
Có, giải pháp là một lựa chọn hợp lệ. Trong hầu hết các DBMS, bạn có thể thực thi rằng chỉ một trong hai FK là "hoạt động" với ràng buộc kiểm tra: CHECK (CorporationID IS NOT NULL AND NaturalPersonID IS NULL OR CorporationID IS NULL AND NaturalPersonID IS NOT NULL)Tôi rất thích giải pháp 1 mặc dù (nhưng đó chỉ là tôi). Nó "sạch" hơn nhiều.
ypercubeᵀᴹ

Vâng, tôi hiểu, nhưng bạn có thể có trong ChecquingAccountbảng một bản ghi OwnerTypeID=1OwnerID=123, chỉ ra rằng đó là một loại Corporation, do đó ID 123trong Corporationbảng. Chủ sở hữu loại cho bạn biết bảng nào và Chủ sở hữu cho bạn biết ID trong bảng đó.
RoKa

1
Làm thế nào là lựa chọn số 1 không thể? Từ "Tổng công ty" về cơ bản có nghĩa là "một doanh nghiệp hợp pháp là một người". Gọi nó là một cái Customersbàn.
Jon của tất cả các giao dịch

Câu trả lời:


15

Cơ sở dữ liệu quan hệ không được xây dựng để xử lý tình huống này một cách hoàn hảo. Bạn phải quyết định điều gì là quan trọng nhất đối với bạn và sau đó thực hiện đánh đổi. Bạn có một vài mục tiêu:

  • Duy trì hình thức bình thường thứ ba
  • Duy trì tính toàn vẹn tham chiếu
  • Duy trì các ràng buộc rằng mỗi tài khoản thuộc về một công ty hoặc một thể nhân.
  • Bảo tồn khả năng truy xuất dữ liệu một cách đơn giản và trực tiếp

Vấn đề là một số trong những mục tiêu này cạnh tranh với nhau.

Giải pháp gõ phụ
Bạn có thể chọn giải pháp gõ phụ trong đó bạn tạo một siêu kiểu kết hợp cả tập đoàn và người. Loại siêu này có thể sẽ có khóa tổng hợp của khóa tự nhiên của loại phụ cộng với thuộc tính phân vùng (ví dụ customer_type). Điều này là tốt cho đến khi bình thường hóa và nó cho phép bạn thực thi tính toàn vẹn tham chiếu cũng như các ràng buộc mà các công ty và người là loại trừ lẫn nhau. Vấn đề là điều này làm cho việc truy xuất dữ liệu trở nên khó khăn hơn, bởi vì bạn luôn phải phân nhánh dựa trên customer_typethời điểm bạn tham gia tài khoản với chủ tài khoản. Điều này có thể có nghĩa là sử dụng UNIONvà có rất nhiều SQL lặp đi lặp lại trong truy vấn của bạn.

Giải pháp hai khóa ngoại
Bạn có thể chọn một giải pháp trong đó bạn giữ hai khóa ngoại trong bảng tài khoản của mình, một cho tập đoàn và một cho người. Giải pháp này cũng cho phép bạn duy trì tính toàn vẹn tham chiếu, chuẩn hóa và loại trừ lẫn nhau. Nó cũng có nhược điểm truy xuất dữ liệu tương tự như giải pháp gõ phụ. Trên thực tế, giải pháp này cũng giống như giải pháp gõ phụ ngoại trừ việc bạn gặp phải vấn đề phân nhánh logic tham gia của mình "sớm hơn".

Tuy nhiên, rất nhiều người điều chỉnh dữ liệu sẽ xem xét giải pháp này kém hơn giải pháp gõ phụ vì cách thức ràng buộc loại trừ lẫn nhau được thi hành. Trong giải pháp gõ phụ, bạn sử dụng các khóa để thực thi tính độc quyền lẫn nhau. Trong hai giải pháp khóa ngoại bạn sử dụng một CHECKràng buộc. Tôi biết một số người có thành kiến ​​không chính đáng đối với các ràng buộc kiểm tra. Những người này thích giải pháp giữ các ràng buộc trong các phím.

Giải pháp phân vùng "không chuẩn hóa"
Có một tùy chọn khác là bạn giữ một cột khóa ngoại duy nhất trên bảng tài khoản chequing và sử dụng một cột khác để cho bạn biết cách diễn giải cột khóa ngoại (của RoKaOwnerTypeIDcột). Điều này về cơ bản loại bỏ bảng siêu loại trong giải pháp gõ phụ bằng cách không chuẩn hóa thuộc tính phân vùng cho bảng con. (Lưu ý rằng đây không hoàn toàn là "không chuẩn hóa" theo định nghĩa chính thức, bởi vì thuộc tính phân vùng là một phần của khóa chính.) Giải pháp này có vẻ khá đơn giản vì nó tránh có một bảng phụ để thực hiện ít nhiều điều tương tự và nó cắt giảm số lượng cột khóa ngoại xuống còn một. Vấn đề với giải pháp này là nó không tránh được sự phân nhánh của logic truy xuất và hơn thế nữa, nó không cho phép bạn duy trì tính toàn vẹn tham chiếu khai báo . Cơ sở dữ liệu SQL không có khả năng quản lý một cột khóa ngoại duy nhất cho một trong nhiều bảng cha.

Giải pháp miền khóa chính được chia sẻ
Một cách mà mọi người đôi khi giải quyết vấn đề này là sử dụng một nhóm ID duy nhất để không có sự nhầm lẫn cho bất kỳ ID cụ thể nào cho dù nó thuộc loại phụ này hay loại khác. Điều này có thể sẽ hoạt động khá tự nhiên trong một kịch bản ngân hàng, vì bạn sẽ không cấp cùng một số tài khoản ngân hàng cho cả công ty và người tự nhiên. Điều này có lợi thế là tránh sự cần thiết của một thuộc tính phân vùng. Bạn có thể làm điều này có hoặc không có bảng siêu loại. Sử dụng bảng siêu loại cho phép bạn sử dụng các ràng buộc khai báo để thực thi tính duy nhất. Nếu không, điều này sẽ phải được thực thi theo thủ tục. Giải pháp này được chuẩn hóa nhưng nó sẽ không cho phép bạn duy trì tính toàn vẹn tham chiếu khai báo trừ khi bạn giữ bảng siêu loại. Nó vẫn không làm gì để tránh logic truy xuất phức tạp.

Do đó, bạn có thể thấy rằng thực sự không thể có một thiết kế sạch sẽ tuân theo tất cả các quy tắc, đồng thời giữ cho việc truy xuất dữ liệu của bạn đơn giản. Bạn phải quyết định nơi mà sự đánh đổi của bạn sẽ diễn ra.


Giải pháp số 2 của tôi thuộc nhóm nào trong bốn nhóm của bạn? "Giải pháp thuộc tính phân vùng không chuẩn hóa" đối với tôi không rõ ràng lắm ..
dendini

@dendini - Giải pháp số 2 của bạn không phù hợp với bất kỳ giải pháp nào tôi đã vạch ra. Điều này là do nó không phù hợp với yêu cầu của một tài khoản thuộc về một pháp nhân. Cách bạn đã xác định các khóa chính của các bảng trung gian, chúng là các giao điểm nhiều-nhiều. Nếu các khóa chính chỉ corporation_idperson_idsau đó về cơ bản bạn sẽ có giải pháp gõ phụ, ngoại trừ bảng siêu loại sẽ được chia thành hai và khóa ngoại sẽ bị đảo ngược, vì vậy mọi người không thể giữ nhiều tài khoản. Loại này đánh bại mục đích.
Joel Brown

Giải thích tuyệt vời. @JoelBrown, ý nghĩa hiệu suất của giải pháp "Hai khóa ngoại", về mặt truy vấn là gì? Ngoài ra, xem xét rằng thay vì 2, có thể có 6 khóa ngoại trở lên: bạn vẫn sẽ đề xuất phương pháp này hay thay vì nghiêng về một khóa khác?
Amadeo Gallardo

1
@AADEoGallardo Câu trả lời là "nó phụ thuộc". Truy vấn theo khóa luôn khá hiệu quả, vì bạn thường có thể tin tưởng vào việc quét chỉ mục ít nhất, nếu không phải là tìm kiếm và đây là những thao tác nhanh. Vấn đề trở thành khi bạn truy vấn trên cả hai khóa trong giải pháp hai khóa ngoại . Ở đây bạn đang yêu cầu trình tối ưu hóa truy vấn thực hiện một / hoặc thao tác. Tốt nhất điều này sẽ tăng gấp đôi chi phí của truy vấn, thường tệ hơn một chút, vì bạn phải truy vấn theo một khóa, sau đó đến khóa kia, sau đó hợp nhất các kết quả.
Joel Brown

@JoelBrown Các phiên bản SQL trong tương lai không chuẩn hóa sẽ cho phép cách tiếp cận này bằng cách cho phép định nghĩa của khóa ngoại tổng hợp dựa trên hai cột RefIDRefTabletrong đó RefTablemột id cố định xác định bảng đích. Có rất nhiều trường hợp sử dụng cho loại khóa này và rất nhiều để duy trì 10 bảng liên kết / phân nhóm trở lên để thực thi tính toàn vẹn. Đối với những trường hợp tôi tự tạo ra điều này key.
djmj
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.