I know that this question is very old, but since it doesn't have an accepted answer yet, I have a couple of ideas.
One possibility is to use ORDBMS features - in other words, use table inheritance. In PostgreSQL you might model it like this:
(See the documentation about PostgresSQL inheritance 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);
Different DBMS vendors will implement this in different ways. In PostgresSQL, there are some important caveats described here:
http://ledgersmbdev.blogspot.com/2012/08/postgresql-or-modelling-part-3-table.html
In particular, note the part about primary and foreign keys not being inherited.
If you don't like the limitations of your DBMS or are using a DBMS that does not have object-relational features, then another option is to use an alternative suggested in the article above and use secondary keys. That would be modeled like this:
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)
);
The above design has some important limitations too (which are also described in the article above). For one thing, though it shouldn't be possible to have an account that is not a private, public, or government customer, it is possible to do so; you can have just accounts, corporate accounts that are neither public nor private... it becomes a nightmare to maintain. The CHECK constraints can hurt performance too, and you'll notice that there is both data duplication in the child entities, as well as missing information in the corporate child entities (country_code).
Which limitations you choose will be dependent on your DBMS vendor and how much headache you want to manage.