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_type
thờ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 UNION
và 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 CHECK
rà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 RoKaOwnerTypeID
cộ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.
OwnerTypeID
trongChecquingAccount
bảng, với1=Corporation
và2=NaturalPerson
? Bằng cách đó, bạn chỉ cần mộtOwnerID
trongChecquingAccount
bảng, mà bạn có thể lập chỉ mục cùng vớiOwnerTypeID
.