数据库设计–Combination of Schemas

我们考虑一个“多对一”的关系表,往往牵涉3个方面,实体表A,实体表B和关系表AB,这里A–>B是many-to-one的关系。如果条件加强一些,A是完全参与在AB关系表中(Totally),怎么理解Totally呢,就是A实体表中的每个实体(entity,其实就是表记录啦,也就是A表中的每一行),都在AB关系表中有对应的项!

好了,简单表述一下,如果:

  1. 表示A和B关系的表AB是A–>B的many-to-one 关系
  2. A是Totally Participate关系表AB

则:我们可以考虑将实体表A和关系表AB合并。通俗点讲:把关系表合并到代表many方的实体表中

举个例子,假设我们有:

  1. 帐号实体表  –>    account =(account_number ,balance)。
  2. 支行实体表 –>    branch =(branch_name ,branch_city,assets)。
  3. 帐号/支行关系表(account_branch),每个支行保存在该支行开户的所有帐号 –>account_branch =(account_number ,branch_name ), 这里是many-to-one关系。
  4. 不允许有“孤儿”帐号,也就是说每个帐号都必须属于一个支行 –> Totally participation哦。

合并后的情况是:

account = (account_number , balance,branch_name )

branch   = (branch_name , branch_city)

注意:

  1. 关系表account_branch就不需要了,并且合并以后的代表many方的实体表account的主键(PK)不变.
  2. 原先在关系表account_branch中的两个外键约束(FK1:account_number到account表;FK2:branch_name到branch表): 我们Drop FK1,Retain FK2。

这里我突然想到了一个数据库设计和C++类设计的不同点,其实用我们平实的语言表述往往是这样的:一个支行拥有多个帐号,这在面向对象语言中是典型的Has-A关系,通常用聚合的方式实现:

设计1:

class account{

};

class branch{

vector<account*> m_accounts;

};

但是在数据库设计中,设计者的思路往往是这样的:

设计2:

class branch{

};

class account{

branch* m_branch;

};

这里我对两个问题的理解不太清晰:

  1. 满足上面提到的情况可以进行Schema的合并,但是一定要合并吗?从实际情况中,在进行合并和不合并的决策时有什么现实的考虑吗?
  2. 在数据库设计中,我好像很少采用C++类设计1中的思路对应的Schema,为什么呢?

 

 

关于第一个问题:
符合第三范式的设计都合并的!
 
关于第二个问题:
这两种设计,从数据的原子上来看,个人认为也没什么不同啊。从内存中来说,如果有多个account 内存中还是会有多分account的,表现形式的不同而已,可以把第一种设计看成是第二种设计的一个变种。第一个实际上是把account 和branch join在一起的一种对应。第二个设计是原子设计,当schema中有冗余,设计不一定是原子的,原子的意思就是说不可再分,不可再分的设计。

你可能感兴趣的:(数据库设计–Combination of Schemas)