我看这个数据模型,我想出了和舒服不舒服。 所以(希望)更有意义,我已经改变了实体名称。 在任何情况下,你会怎么下面的模型?
我有3个实体。 GovernmentCustomer,PrivateCustomer,PublicCustomer。 私人和公共客户都CorporateCustomers。 企业和政府客户的帐户。 所有帐户共享相同的密钥空间(所以如果PrivateCustomer具有1的PK它不应该是可能的公共或GovernmentCustomer有1一个PK)。 CorporateCustomers有一些1:M关系,这GovernmentCustomer的没有。 PublicCustomers有一些1:M关系,这PrivateCustomers没有。
传承:
Account
CorporateCustomer
PrivateCustomer
PublicCustomer
GovernmentCustomer
现在我的模型有5桌。 “帐户”表是这个层次,每个子表的PK是一个FK其父的PK的根源。 因此,所有的表都具有相同的PK。
所以,是的,你会怎么建模呢? 我希望事情一直没有去疯狂错在这里:)。
编辑:
另外: - 我想的DB要照顾裁判完整性不应用程序。 - 它不可能而不被私人或公共客户存在CorporateCustomer。 它的抽象。
的一种方法是:
ACCOUNTS -> ACCOUNT_CUSTOMERS <- CUSTOMERS
让客户有一个CUSTOMER_TYPE列,它是类型的企业(C),私人(P),公共(Z),政府(G)。 由于所有公共和pivate客户也是企业,如果你需要让所有的企业客户,你可以这样做:
SELECT *
FROM ACCOUNTS
, ACCOUNT_CUSTOMERS
, CUSTOMERS
WHERE ACCOUNTS.ID = ACCOUNT_CUSTOMERS.ACCT_ID
AND CUSTOMERS.ID = ACCOUNT_CUSTOMERS.CUST_ID
AND CUSTOMERS.CUSTOMER_TYPE in ('C','P','Z')
我用ORACLE语法,但我认为你的想法。
In response to your edit:
这听起来像你只有两个类型的客户。 企业和政府。 这是更容易呢。 我会用客户的布尔指标叫做PUBLIC_IND,当假的是私有的,或者其他类型的类似ENTITY_TYPE这可能是私人(P),公共(Z),或无(N)。 然后,如果你想获得的所有公共公司客户的用户:
SELECT *
FROM ACCOUNTS
, ACCOUNT_CUSTOMERS
, CUSTOMERS
WHERE ACCOUNTS.ID = ACCOUNT_CUSTOMERS.ACCT_ID
AND CUSTOMERS.ID = ACCOUNT_CUSTOMERS.CUST_ID
AND CUSTOMERS.CUSTOMER_TYPE in ('C')
AND CUSTOMERS.ENTITY_TYPE = 'Z'
在您承诺将每类在同一个表,我想看看他们参与的关系 -而不是属性。 这是微不足道的某些字段保留为空,如果记录类型是“X”,但它是令人难以置信的笨拙尝试有只适用于特定的记录表中的关系。
如果与其他实体类的关系是完全一样的,那么你就可以没有真正的缺点他们的东西都在一个表中。
我想你应该有一个帐户和客户表,用CustomerRelationship表一起。 不同类型的客户可以用某种类型码来区分,并且关系可以用CustomerRelationship表得到维护。
我同意,如果不同类型客户的是一个类似于customerType场就足够了别人。
这么说,也许仅仅是企业客户共用一张桌子,但政府客户有足够的不同,他们需要在自己的表中定义。 在有正当理由的情况下,一个设计来帮助你强制PK的约束将有会由ID(PK的约束)引用的所有客户MasterAccount表,对下一级参考,其类型层次结构(企业或政府)。
你仍然需要映射1个*关系,这你可以用另一个两张表做 - 一个关系表和账户关系的映射表。
除非有多数民众赞成由不同类型的cusomter中跟踪的属性显著差异,我只是有一些CustomerType场一个表称为帐户。 你可以表达1:通过具有FK到的AccountID细节表米关系。
编辑:现代数据库可以增加数据完整性规则超越FK参照完整性。 例如与SQL Server,你可以添加CHECK约束强制执行ACCOUNTTYPE是GovernmentCustomer某些细节表的主人。 它可能是这个样子:
CREATE FUNCTION EnforceGovernmentCustomer(@AccountID int)
RETURNS bit
AS
BEGIN
DECLARE @retval bit
SELECT @retval = 0
SELECT @retval = 1
FROM Account
WHERE AccountID = @AccountID AND AccountType = 3
RETURN @retval
END;
GO
ALTER TABLE GovernmentCustomerDetail
ADD CONSTRAINT chkGovernmentCustomer CHECK (dbo.EnforceGovernmentCustomer(AccountID) = 1);
GO
我知道这个问题已经很老了,但因为它没有一个公认的答案,我有一对夫妇的想法。
一种可能性是使用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
特别要注意的关于未继承主键和外键的一部分。
如果你不喜欢你的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供应商和多少头痛要管理。