如何建模与RDBMS这种多重继承关系?(How to model this multiple inh

2019-09-16 13:52发布

我看这个数据模型,我想出了和舒服不舒服。 所以(希望)更有意义,我已经改变了实体名称。 在任何情况下,你会怎么下面的模型?

我有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。 它的抽象。

Answer 1:

的一种方法是:

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'


Answer 2:

在您承诺将每类在同一个表,我想看看他们参与的关系 -而不是属性。 这是微不足道的某些字段保留为空,如果记录类型是“X”,但它是令人难以置信的笨拙尝试有只适用于特定的记录表中​​的关系。

如果与其他实体类的关系是完全一样的,那么你就可以没有真正的缺点他们的东西都在一个表中。



Answer 3:

我想你应该有一个帐户和客户表,用CustomerRelationship表一起。 不同类型的客户可以用某种类型码来区分,并且关系可以用CustomerRelationship表得到维护。



Answer 4:

我同意,如果不同类型客户的是一个类似于customerType场就足够了别人。

这么说,也许仅仅是企业客户共用一张桌子,但政府客户有足够的不同,他们需要在自己的表中定义。 在有正当理由的情况下,一个设计来帮助你强制PK的约束将有会由ID(PK的约束)引用的所有客户MasterAccount表,对下一级参考,其类型层次结构(企业或政府)。

你仍然需要映射1个*关系,这你可以用另一个两张表做 - 一个关系表和账户关系的映射表。



Answer 5:

除非有多数民众赞成由不同类型的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


Answer 6:

我知道这个问题已经很老了,但因为它没有一个公认的答案,我有一对夫妇的想法。

一种可能性是使用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供应商和多少头痛要管理。



文章来源: How to model this multiple inheritance relationship with a RDBMS?