想象一下,我有一个Orders表,其中包含OrderID(PK),CustomerID,CustomerOrderN等列。现在我需要添加“关闭”订单的可能性,并指定订单关闭的原因(例如“提供的价格对于客户而言太高”,“不可用”,“客户要求关闭订单”)。
问题1。在数据库设计中实现这一点的最佳和正确方法是什么?
我认为最好的方法是创建Closed列,该列可以为null(如果订单已打开),如果不为null(即如果订单已关闭)则该值指向另一个表OrderCloseReasons。
问题2。如果我已经拥有:)一个布尔列在Orders表中关闭,现在我需要实现指定关闭原因的可能性。我不能重构太多因为系统已经不那么小了,所以重构数据库方案很难。在这种情况下,增加指定关闭原因的可能性的最佳方法是什么?
我认为如果我只是将CloseReasonID列添加到Orders表中,那就不太好了。但我不确定。
提前谢谢。
答案 0 :(得分:4)
如果您有一堆特定的接近原因,并且您需要能够根据特定类型的接近原因(例如,通过理由X获取所有内容)执行查询,那么您的建议是什么是一个好主意 - null或关闭原因ID。
另一方面,如果你不需要搜索等,你可以简单地关闭一个列,另一列描述它被关闭的原因。
答案 1 :(得分:3)
我建议使用StatusCode列(可能是int数据类型)和包含StatusCode(int)和StatusCodeDescription(varchar)的单独表。如果您或您的最终用户以后想到另一种可能的状态,那么这将为您提供更大的灵活性。
答案 2 :(得分:1)
就个人而言,我会按照你的建议做查找表,但称之为状态。我会将Orders表中Status表的外键设为int,而不是null,默认值为1.
然后状态表中的记录将是(1)打开,(2)关闭原因一,(3)关闭原因二,等等。这样你就可以映射到更高层的枚举而无需做任何事情特别适用于您的存储过程。也就是说,你所做的就是在SELECT中包含StatusID,而不必将处理null视为一件事而将查找值视为另一件事。
答案 3 :(得分:0)
将null和reason合并到一个可以为空的文本列中并不是一个好主意,因为它可能在几天后很难被其他程序员甚至是你读取。
有两列,一个是由David指定的布尔值或状态码,并且为了理由而单独列。这为您的设计提供了更多的可读性。
但我会提前一步,财务相关软件的最佳实践是内置审计跟踪,因为我当然想知道..
“谁关闭了订单?” “什么时候关闭?” “它重新开放吗?”
审计跟踪通常由另一个表组成,例如
OrderAudit - > AuditID - >订单ID - > ChangeMadeBy - > ChangeDateTime - > ChangeColumn - > ChangeValue
这将完全控制谁对此订单以及何时做了什么。
答案 4 :(得分:0)
另一张表格,其中包含已关闭订单的结果。
它没有违反1NF,因为您没有在数据库模式中引入空值,并且您绝对保证您的更改不会影响现有的内容(在这种情况下,您明确指出这是一个主要问题)
修改
参见例如“数据库日期中的第一范式确实意味着什么”:2000-2006年的着作(Springer-Verlag,2006)。可能还可以在互联网上找到独立的纸张。
从“数据库系统简介”,8ed。 :“当且仅当在该relvar的每个合法值中,每个元组包含每个属性的一个值时,relvar在1NF中。” (并且null不可能是值,因为它不等于它自己。)