Я знаю, что этот вопрос очень старый, но так как на него еще не принято ответа, у меня есть пара идей.
Одна из возможностей - использовать функции 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);
Различные поставщики СУБД будут реализовывать это по-разному. В PostgresSQL есть несколько важных предостережений, описанных здесь:
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)
);
Приведенный выше дизайн также имеет некоторые важные ограничения (которые также описаны в статье выше). С одной стороны, хотя не должно быть возможности иметь учетную запись, которая не является частным, государственным или государственным клиентом, это возможно сделать; Вы можете иметь только учетные записи, корпоративные учетные записи, которые не являются ни общедоступными, ни частными ... это становится кошмаром. Ограничения CHECK
также могут снизить производительность, и вы заметите, что в дочерних сущностях есть как дублирование данных, так и недостающая информация в дочерних корпоративных объектах (код страны).
Какие ограничения вы выберете, будет зависеть от вашего поставщика СУБД и от того, какой головной болью вы хотите управлять.