我知道這個問題很舊,但由於它還沒有被接受的答案,所以我有幾個想法。
一種可能性是使用ORDBMS功能 - 換句話說,使用表繼承。在PostgreSQL你可能會喜歡這個型號:
(請參閱有關PostgreSQL的繼承http://www.postgresql.org/docs/9.3/static/ddl-inherit.html的文檔)
CREATE TABLE account
(
account_id INT,
PRIMARY KEY(account_id)
);
CREATE TABLE corporate_customer
(
company_name VARCHAR(32),
country_code CHAR(2),
PRIMARY KEY(company_name)
) INHERITS(account);
CREATE TABLE private_corp_customer
(
private_comp_id INT,
company_owner VARCHAR(32),
PRIMARY KEY(private_comp_int)
) INHERITS(corporate_customer);
CREATE TABLE public_corp_customer
(
stock_ticker VARCHAR(6),
PRIMARY KEY(stock_ticker)
) INHERITS(corporate_customer);
CREATE TABLE government_customer
(
dept_nbr INT,
country CHAR(2),
PRIMARY KEY(dept_nbr)
) INHERITS(account);
不同的DBMS廠商會以不同的方式實現這一點。在PostgreSQL中,這裏有描述一些重要的注意事項:
http://ledgersmbdev.blogspot.com/2012/08/postgresql-or-modelling-part-3-table.html
特別要注意關於未繼承主鍵和外鍵的一部分。
如果您不喜歡數據庫管理系統的限制或者使用的是不具備對象關係特性的數據庫管理系統,那麼另一種選擇是使用上述文章中提出的替代方案並使用輔助鍵。這將建模如下:
CREATE TABLE account
(
account_id INT,
account_type INT NOT NULL,
PRIMARY KEY(account_id),
UNIQUE (account_id, account_type)
);
CREATE TABLE corporate_customer
(
account_id INT,
account_type INT NOT NULL CHECK(account_type IN (1,2)),
company_name VARCHAR(32),
country_code CHAR(2),
PRIMARY KEY(account_id, account_type),
FOREIGN KEY(account_id, account_type) REFERENCES account(account_id, account_type),
UNIQUE(account_id, account_type, company_name)
);
CREATE TABLE private_corp_customer
(
account_id INT,
account_type INT NOT NULL CHECK(account_type = 1),
company_name VARCHAR(32),
company_owner VARCHAR(32),
PRIMARY KEY(account_id, account_type, company_name),
FOREIGN KEY(account_id, account_type, company_name) REFERENCES corporate_customer (account_id, account_type, company_name)
);
CREATE TABLE public_corp_customer
(
account_id INT,
account_type INT NOT NULL CHECK (account_type = 2),
company_name VARCHAR(32),
stock_ticker CHAR(6),
PRIMARY KEY(account_id, account_type, company_name),
FOREIGN KEY(account_id, account_type, company_name)
REFERENCES corporate_customer (account_id, account_type, company_name)
) INHERITS(corporate_customer);
CREATE TABLE government_customer
(
account_id INT,
account_type INT NOT NULL CHECK(account_type = 3),
dept_nbr INT,
country_code CHAR(2),
PRIMARY KEY(account_id, account_type),
FOREIGN KEY(account_id, account_type) REFERENCES account(account_id, account_type),
UNIQUE(account_id, account_type, dept_nbr)
);
上述設計也有一些重要的限制(這也在上面的文章中描述)。首先,雖然不應該有一個不是私人,公共或政府客戶的賬戶,但可以這樣做;你可以只擁有帳戶,既不公開也不私密的公司帳戶......這成爲一個噩夢來維護。約束條件也會損害性能,並且您會注意到子實體中存在數據重複以及公司子實體(country_code)中缺少信息。
您選擇哪些限制將取決於您的DBMS供應商以及您想要管理多少頭痛。
如果我正確理解這種方法,我的應用程序將不得不管理一些數據完整性。例如,對於具有政府客戶類型的賬戶可能有許多財務報表。只有公司客戶應該有這種關係。我對嗎?我更新了這個問題,以使ref的完整性更清晰。 – 2009-06-19 12:51:48
@TheDeeno,我更新了答案以反映您的意見。 – 2009-06-19 14:41:25
@ eed3si9n謝謝!我將不得不看看是否可以考慮自定義檢查約束進行建模。所以你一般反對5桌分享PK想法? – 2009-06-19 20:10:15