建模分层数据结构

时间:2012-03-01 23:26:09

标签: database relational-database relationship

20120304 - 简化问题

假设我们有实体R,D和E以及这种关系基数

  • R< n:m> d
  • D< 1:n> ë

此规范的映射是直截了当的,但我们还有另一项要求:

  • R< n:m> E

边条件:如果E1与某些D1相关且此D1与R1相关,则E1可能只会被“分配”到R1。

不幸的是,即使E2与D2有关,但与R2有关 - E2可能与R2无关。

  • 我正在寻找关系数据库模型。
  • 如果D从Ra分离并重新连接到另一个Rb,则不需要多次更新的模型。在这种情况下,所有Es的D都需要从Ra分离并附加到Rb。

20120305 - 解决方法?

朋友建议创建一个实体DxR,它通过元组(D,R)链接其D和R。然后创建一个关系

  • DxR< n:m> ë

唔...

20120302 - 原始问题

系统由顶级区域(Z)组成。区域可能有多个区域(R)

所谓的部门(D)可能会分配到地区。只有当每个区域属于不同的区域时,才能将一个部门分配到多个区域。

最后,员工(E)属于一个且仅属于一个部门

只有当员工的部门属于该地区时,员工才可能被分配到某个地区。

重要提示: 员工不必属于其所属部门所属的所有区域。

假设在以下图形E1中属于D1。 E1也应该属于R1,但​​不属于R2 - 尽管D1属于R1和R2:

-     Z            Z
-   __|___      ___|___
-   R1   R      R2    R
-    \_________/
-     D1         

问:请提出关系数据库的表格结构,该结构模拟上述规范?

1 个答案:

答案 0 :(得分:1)

这个问题在某种意义上是非常具体的,有些人可能会认为它过于本地化。然而,还有一个更普遍适用的想法,可能对将来的其他人有用,所以问题太具体,这不一定是真的。

这些业务规则中真正有趣的部分是这个:(我的重点补充)

  

可能会将一个部门分配到多个区域,仅限于每个区域   区域属于不同的区域

这是一个模式,可以声明性地捕获几乎所有已声明的业务规则,而不必诉诸任何触发器。

create table ZONE
( ID int not null
, NAME varchar(50) not null
, constraint PK_ZONE primary key clustered (ID)
)

create table REGION
( ZONE_ID int not null
, REGION_ID int not null
, NAME varchar(50) not null
, constraint PK_REGION primary key clustered (ZONE_ID, REGION_ID)
, conttraint FK_REGION__ZONE foreign key (ZONE_ID) 
    references ZONE (ID)
)

create table DEPARTMENT
( ID int not null
, NAME varchar(50) not null
, constraint PK_DEPARTMENT primary key clustered (ID)
)

create table EMPLOYEE
( ID int not null
, NAME varchar(50) not null
, DEPT_ID int not null
, constraint PK_EMPLOYEE primary key clustered (ID)
, constraint FK_EMPLOYEE__DEPARTMENT foreign key (DEPT_ID) 
    references DEPARTMENT (ID)
)

上面的表非常明显。但是,有一个特殊的怪癖:REGION表有一个复合主键,包括FK到ZONE。这对于传播有关区域内必须区分的部门的约束非常有用。

将部门分配到地区需要交叉表:

create table DEPT_ASGT -- Department Assignment
( REGION_ID int not null
, DEPT_ID int not null
, ZONE_ID int not null
, constraint PK_DEPT_ASGT (REGION_ID, DEPT_ID)
, constraint FK_DEPT_ASGT__REGION foreign key (ZONE_ID, REGION_ID) 
    references REGION (ZONE_ID, ID)
, constraint FK_DEPT_ASGT__DEPARTMENT foreign key (DEPT_ID) 
    references DEPARTMENT (ID)
, constraint UN_DEPT_ASGT__ZONES unique nonclustered (ZONE_ID, DEPT_ID)
)

此交集表非常正常,因为它具有链接到的每个表的外键。这个交集表的特殊之处在于唯一约束。这就是强制规则,即部门不能位于同一区域内的两个不同区域。

最后,我们需要将员工映射到部门和区域。这需要另一个交叉表:

create table EMP_ASGT -- Employee Assignment
( REGION_ID int not null
, DEPT_ID int not null
, EMPLOYEE_ID int not null
, constraint PK_EMP_ASGT (REGION_ID, DEPT_ID, EMPLOYEE_ID)
, constraint FK_EMP_ASGT__DEPT_ASGT (REGION_ID, DEPT_ID) 
    references DEPT_ASGT (REGION_ID, DEPT_ID)
, constraint FK_EMP_ASGT__EMPLOYEE (EMPLOYEE_ID) refernces EMPLOYEE (ID)
)

您将注意到EMPLOYEE表具有DEPARTMENT的外键 - 这强制执行每个员工只能属于一个部门的规则。 EMP_ASGT表添加了有关员工参与的区域的详细信息。由于员工可能不参与其部门所在的每个区域,EMP_ASGT表将员工连接到这些区域他们有一些参与。

这是需要触发器或其他程序逻辑的地方。您需要确保EMPLOYEE.department_id与EMP_ASGT中的记录保持一致。您可以尝试通过使EMPLOYEE的PK成为ID和DEPT_ID的复合来将其推入声明性参照完整性,但这将迫使您决定是否要违反3NF或使您的员工部门更改程序丑陋。在一天结束时,确保EMP_ASGT不同意EMPLOYEE.DEPT_ID的一点点触发器将不那么麻烦。