我知道这个问题已经很老了,但是由于它还没有一个公认的答案,所以我有几个想法。
一种可能性是使用 ORDBMS 特性——换句话说,使用表继承。在 PostgreSQL 中,你可以这样建模:
(请参阅有关 PostgresSQL 继承的文档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 供应商将以不同的方式实现这一点。在 PostgresSQL 中,这里描述了一些重要的警告:
http://ledgersmbdev.blogspot.com/2012/08/postgresql-or-modelling-part-3-table.html
特别要注意关于主键和外键不被继承的部分。
如果您不喜欢 DBMS 的限制或正在使用不具有对象关系功能的 DBMS,那么另一种选择是使用上面文章中建议的替代方法并使用辅助键。那将是这样建模的:
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)
);
上述设计也有一些重要的限制(在上面的文章中也有描述)。一方面,虽然不可能拥有不是私人、公共或政府客户的帐户,但有可能这样做;你可以只拥有既不是公共也不是私人的帐户、公司帐户……维护起来简直就是一场噩梦。约束也会影响性能,CHECK
您会注意到子实体中存在数据重复,以及公司子实体 (country_code) 中缺少信息。
您选择哪些限制将取决于您的 DBMS 供应商以及您想要管理的头痛程度。