数据库设计一对多对多

时间:2011-11-03 21:43:21

标签: database oracle database-design

我正在为Java Web应用程序工作流应用程序进行数据库设计,以跟踪和检查各种业务产品(文档)。但是我的设计和实施存在很多不确定因素 这是我的表格:

  • WORK_FLOW_CLASS - 产品类型工作流程的定义表,即:报告,演示文稿,工程计算

  • ROLE_CLASS - 工作流程角色的定义表,即:发起人,检查员,审批人,经理

  • WORK_ITEM_CLASS - 代表某种纸质表格的工作项定义表,即:分配表,计算清单,报告审核表,结账清单等。这些表格需要由多个角色来处理在被视为完成之前的某个订单

  • WORK_ACTION_CLASS - 工作项操作的定义,即:Checker的完整计算核对表(WORK_ITEM)(a ROLE),完整的审核报告({{1 }})经理(WORK_ITEM),审批人完成审核报告(ROLE)(WORK_ITEM

  • ROLE - 将WORK_FLOW_SEQUENCE与MANY WORK_FLOW_CLASS相关联的定义表,即部门ABC级别1计算序列为:(1)分配表格,(2)计算清单,(3)收尾清单。部门XYZ 1级计算顺序为:(1)分配表,(2)结账清单[XYZ选择不在其Calc工作流程中进行检查清单]。

第一个问题: WORK_ACTION_CLASS是否应该使用FK将其与WORK_ITEM_CLASS相关联?

或者我应该使用中级表来提供关系?我认为后者是不必要的,因为我不需要将WORK_ACTION与多个WORK_ITEMS相关联,只需要一个。

当用户启动新的工作流实例时,我的计划是查询CLASS表以获取所选WORK_FLOW_CLASS的详细信息,并将它们实例化为下表。

  • WORK_ITEM_CLASS - 工作流程的实际实例 - 我想是购物车订单

  • WORK_FLOW_INSTANCE - WORK_ITEM的工作流程实例行项目 - 我想就像订单中的产品

  • WFI_WORK_ITEMS - 工作流程实例工作项目操作

以下是第二个问题需要帮助的地方。

是否应该有两个单独的表WFI_WORK_ITEM_ACTIONSWFI_WORK_ITEMS,还是应该有一个复合表?我将只需要查询工作流实例中的WORK_ITEMS以及带有子步骤WORK_ACTIONS的WORK_ITEMS。

这里是质疑的两个表的详细信息。抱歉,我不知道描绘我的架构的最佳方式。

WFI_WORK_ITEM_ACTIONS

我似乎在这两个表中有很多冗余信息。但我读过有时会执行去规范化表。

非常感谢我对我的设计的任何帮助。

修改 冗余数据的意思是两个表都列出WFI_WORK_ITEMS ============== WFI_WORK_ITEM_ID (PK) WORKFLOW_INSTANCE_ID (FK) WORK_ITEM_CLASS_ID (FK) STEP_NUM LAST_DATE STATUS IS_ACTIVE WFI_WORK_ITEM_ACTION ==================== WFI_WORK_ITEM_ACTION_ID (PK) WORKFLOW_INSTANCE_ID (FK) WFI_WORK_ITEM_ID (FK) WORK_ITEM_CLASS_ID (FK) STEP_NUM WORK_ACTION_CLASS_ID (FK) ACTION_OWNER LAST_DATE DATE STATUS IS_ACTIVE WORKFLOW_INSTANCE_ID我的想法是,如果我想知道WORKFLOW的特定实例的WORK_ITEM_ACTIONS,我可以通过查询表来获取它{ {1}}没有加入'WFI_WORK_ITEM'表格。也许这是错误的想法。 WORK_ITEM_CLASS_ID也是如此。通过查询WFI_WORK_ITEM_ACTION表,我知道了ACTION用于的WORK_ITEM的类型。

这是一个更好的设计吗?

WFI_WORK_ITEM
==============
WFI_WORK_ITEM_ID (PK) 
WORKFLOW_INSTANCE_ID (FK) 
WORK_ITEM_CLASS_ID (FK)
WORK_ITEM_STEP_NUM
WORK_ITEM_LAST_DATE
WORK_ITEM_STATUS
WORK_ITEM_IS_ACTIVE


WFI_WORK_ITEM_ACTION
====================
WFI_WORK_ITEM_ACTION_ID (PK) 
WORKFLOW_INSTANCE_ID (FK)
WFI_WORK_ITEM_ID (FK) 
WORK_ITEM_CLASS_ID (FK)
WORK_ACTION_STEP_NUM
WORK_ACTION_CLASS_ID (FK)
ACTION_OWNER
WORK_ACTION_LAST_DATE
WORK_ACTION_STATUS
WORK_ACTION_IS_ACTIVE

1 个答案:

答案 0 :(得分:4)

您应该始终以第三范式(3NF)设计表格。如果您理解并减轻影响,那么恢复较小的形式(通常是出于性能原因)是完全可以接受的,但以3NF开始

要记住的(略微简化的)规则是表中的每个非键列都应该依赖于:

  • 钥匙,
  • 整个密钥,
  • 除了钥匙外什么都没有,
  • “所以帮助我,Codd” - 一点DBA的幽默(我的意思是“小”)。

第一个问题很简单。

一对多关系最好在“many”表中表示为外键。所以你提出的建议是明智的。它允许您自动限制关系。如果你有一个单独的连接表(用于多对多),你需要诉诸“欺骗”来强制执行一对多的关系。

关于你的第二个问题,你需要查看上面的“Codd”规则并自己思考:每个表中的这些行究竟代表什么?如果工作项操作是与工作项不同的对象(它们可能与相关,但是,如果它们不表示相同的对象,则它们是不同的),它们应该位于不同的表中。

此外,看起来你在那里有一对多的关系(一个项目可以有很多动作)所以它们应该仅仅因为这个原因而在不同的表中。

关于冗余信息的查询:如果他们真的 多余,则应修复它们。

step_num为例,这究竟代表什么?如果它是工作项目的属性,它根本不应该位于工作 action 表中。

您可以从那里删除它,如果您想知道工作操作表中某行的步骤编号,您将使用外键加入工作项表。

如果它是工作操作的属性,则应将其从工作项表中删除,因为它没有意义。您可能有两个操作,每个操作都有不同的步骤编号,那么在这种情况下父项的步骤编号是多少?

当然,对于项目操作,您可能有 distinct 步骤编号 - 在这种情况下,我会考虑重命名以使意图明确,例如{ {1}}和item_step_num

底线是从3NF开始。如果在某些时候您的数据库运行速度太慢,那么然后会考虑将其恢复为较小的形式。然后,您可以在此处询问另一个问题,了解如何识别和缓解由此产生的问题(例如,两个地方可能存在数据不一致,并使用触发器来防止这种情况)。