工作订单数据库中从属表的最佳设计

时间:2016-05-24 21:16:04

标签: sql database-design

我在数据库中工作以控制工单但我在设计数据库方面遇到了一些麻烦。

我有一张桌子:

TABLE WorkOrder
 - WorkOrderID 
 - DateOfRequest 
 - Requestor 
 - DrawingNumber 
 - Quantity

但我不知道如何以规范化方式创建以下表格:

订单必须只有一个状态:已批准或已拒绝。

  • 已批准订单包含ApprovedBy字段,并属于以下两种情况之一:
    • 已发送:如果订单已下达,则应包含DeliveredDateReceivedByReceivedQuantity。我们需要数量,因为收到的数量可能少于或多于请求的数量。
    • 已取消:如果订单已取消,则应包含CancelDateCanceledByCanceledReason
  • 已拒绝订单仅包含RejectedByRejectedReason字段。

我希望有人可以给我一个处理这个头脑风暴的想法

2 个答案:

答案 0 :(得分:0)

我会使用看起来像这样的结构:

    TABLE work_orders
     - id
     - drawing
     - quantity

    TABLE statuses
     - id
     - work_order_id (foreign key to work_orders)
     - by            (covers requested by, approved by, rejected by and canceled by)
     - date
     - type        (delivered | canceled | rejected | requested)

    TABLE receptions  
     - id            (same as the status id, one-to-one)
     - quantity  

    TABLE cancelations
     - id            (same as the status id, one-to-one)  
     - reason

    TABLE rejections
     - id            (same as the status id, one-to-one)  
     - reason

创建订单时,您需要在work_orders表中添加一个条目,以及所请求类型的新状态。

订单交付时,您添加新状态和具有相同ID的接收。您甚至可以使用此系统处理多个部分交付。

当订单被拒绝或取消时,您可以添加状态以及相应表格中的条目。这些表可以合并,但是如果您决定为这些类型的状态存储不同的信息,那么您将遇到麻烦,所以我可能会将它们从一开始就分开。

要了解订单的当前状态,您只需查询状态表,按日期排序,然后获取最后一个条目。您甚至可以通过获取所有相应的状态来显示订单的整个时间表。此外,此结构允许您交付订单的一部分,其余部分已取消。

我希望这一切都有道理。随意询问您是否要我详细说明。

答案 1 :(得分:0)

您有两个状态值,已批准和已拒绝。 Approved进一步细分为两个子状态值:Delivered和Cancelled。让我们首先说我们有三个状态值,拒绝,已交付和已取消,看看我们的设计是如何运作的。

WorkOrder表将如问题所示,因此我们需要一个状态表,它将状态与工单相关联,包含所有状态值共有的任何数据,并提供有关数据位置的提示可以找到状态。

create table Status(
    WOID    int  primary key,
    Value   char( 1 ) check( Value in ('R', 'D', 'C' )),
    By      int   not null, -- who approved, rejected or authorized this status
    AsOf    date  not null, -- and when.
    constraint FK_Status_WorkOrder( WOID)
        references WordOrder( ID ),
    constraint FK_By_Employee( By )
        references Employee( ID )
);

此时,我们知道将有多个表用于包含状态详细信息(命名为猜测,如Rejects,Deliveries,Cancels)。但是我们不能为这些其他表中的每一个定义一个FK字段,并且定义三个这样的字段会使正在运行的数据库的设计和数据完整性维护复杂化。幸运的是,有一种解决方法。

我们所做的是将三个详细信息表中的FK引用回状态表。但首先,我们必须通过添加一个额外的约束来准备Status表:

create table Status(
    ...,
    constraint UQ_Status_By_Type unique( WOID, Value )
);

如果您正在关注,您可能想知道我们为什么要在两个字段上创建唯一索引,其中一个字段本身就是唯一的。原因是定义了三个细节表可以锁定的钩子。

create table Rejects(
    WOID    int  primary key,
    Value   char( 1 ) check( Value = 'R' ),
    Reason  varchar( 10 ),
    constraint FK_Rejects_Status( WOID, Value )
        references Status( WOID, Value )
);

其他详细信息表的定义相似。

让我们来看看到目前为止我们有什么。 Status表的WOID字段确保任何工单的状态不能超过一个,并且检查约束确保它必须是Rejected,Delivered或Cancelled之一。如果将WO状态定义为,例如,已拒绝,则必须在状态表中输入值为“R”的条目。因此,可以仅为该WO制作拒绝表中的相应条目(其可以仅包含值'R')。系统将拒绝Delivered表中的条目(其状态值只能为'D')。

因此保持了数据完整性。不幸的是,数据完整性在设计结束时经常出现问题。我认为它应该是主要的设计原则。

当然,可以进行改进。例如,不是使用检查约束,而是Status表的Value字段本身可以是查找表的外键。这样可以在以后稍微添加新的状态值。