2010-12-23 30 views
6

tôi có một bảng gọi là PartyChannel có cột sauchính nước ngoài có điều kiện trong SQL

ID, ChannelID, ChannelType 

ChannelID cửa hàng MailID hoặc PhoneID hoặc EmailID tùy thuộc vào ChannelType.

vậy làm cách nào tôi có thể tạo khóa ngoài giữa PartyChannel và cả ba bảng (Thư, Email và Điện thoại) tùy thuộc vào loại kênh.

+3

MailID, PhoneID, EmailID là ba tên miền riêng biệt và không thể, không được mô hình hóa bằng một cột ChannelID duy nhất. Đây là thứ cơ bản. – onedaywhen

Trả lời

4

AFAIK, bạn không thể thực hiện việc này bằng khóa ngoài tiêu chuẩn. Tuy nhiên, bạn có thể thực hiện một cái gì đó để giúp đảm bảo tính toàn vẹn dữ liệu bằng cách sử dụng trình kích hoạt. Về cơ bản, trình kích hoạt sẽ kiểm tra sự hiện diện của một "khoá ngoại" trên bảng được tham chiếu - giá trị phải có - bất cứ khi nào có chèn hoặc cập nhật trên bảng tham chiếu. Tương tự, xóa từ bảng được tham chiếu có thể có trình kích hoạt kiểm tra các bản ghi trên bảng tham chiếu sử dụng khóa đang bị xóa.

Cập nhật: Mặc dù tôi đã đi đúng cho câu trả lời "Tôi đồng ý với nhận xét còn lại bởi @onedaywhen rằng đây thực sự là một vấn đề do thiết kế gây ra có thể khiến bạn cân nhắc lại thiết kế của mình. Tức là, bạn nên có ba cột khác nhau thay vì một cột tham chiếu ba bảng. Bạn sẽ chỉ để lại hai cột khác null khi một được lấp đầy mà, lần lượt, sẽ cho phép bạn sử dụng các phím tiêu chuẩn nước ngoài. Bất kỳ mối quan ngại nào về điều này sẽ "sử dụng quá nhiều không gian" là ngớ ngẩn; nó đại diện cho một trường hợp nghiêm trọng của việc tối ưu hóa sớm - nó chỉ không quan trọng.

7

Bạn có thể sử dụng PERSISTED COMPUTED cột có tuyên bố trường hợp nhưng cuối cùng, nó không mua gì ngoài chi phí.

Giải pháp tốt nhất là mô hình hóa chúng dưới dạng ba giá trị riêng biệt để bắt đầu.

CREATE TABLE Mails (MailID INTEGER PRIMARY KEY) 
CREATE TABLE Phones (PhoneID INTEGER PRIMARY KEY) 
CREATE TABLE Emails (EmailID INTEGER PRIMARY KEY) 

CREATE TABLE PartyChannel (
    ID INTEGER NOT NULL 
    , ChannelID INTEGER NOT NULL 
    , ChannelType CHAR(1) NOT NULL 
    , MailID AS (CASE WHEN [ChannelType] = 'M' THEN [ChannelID] ELSE NULL END) PERSISTED REFERENCES Mails (MailID) 
    , PhoneID AS (CASE WHEN [ChannelType] = 'P' THEN [ChannelID] ELSE NULL END) PERSISTED REFERENCES Phones (PhoneID) 
    , EmailID AS (CASE WHEN [ChannelType] = 'E' THEN [ChannelID] ELSE NULL END) PERSISTED REFERENCES Emails (EmailID) 
) 

Disclaimer

chỉ vì bạn có thể không có nghĩa là bạn nên.

+0

Điều này khá hoang dã. Nó có hoạt động trong tất cả các triển khai SQL chính không? –

+0

@Mark: nó hoạt động với SQL Server 2005 & 2008. Ngoài ra, tôi thành thật không có ý tưởng, đó là một bài tập tinh thần tốt . Một tuyên bố từ chối có thể là theo thứ tự mặc dù: * chỉ vì bạn không thể có nghĩa là bạn nên! * –

+0

Nó hoạt động trong SQL Server mặc dù ChannelType của bạn phải là một char hoặc varchar chứ không phải là một int. Một lần nữa - +1 - cảm ơn. Khá thú vị và khác thường. Tôi vẫn đồng ý với @onedaywhen rằng đây không phải là thiết kế tốt nhưng tôi đánh giá cao bài học trong SQL không bình thường mà bạn đã cung cấp! –

4

Loại phụ Email, Mail, Phone đến Channel.

alt text

+0

Đây là mô hình gen-spec, như được trình bày trong mô hình quan hệ. Sơ đồ minh họa các phím độc đáo. Làm tốt lắm. –

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