为什么使用common-lookup表来限制实体的状态错误?

Pet*_*ron 23 database-design

根据Anith Sen 应该避免五个简单数据库设计错误,使用通用查找表来存储实体的可能状态是一个常见的错误.

编辑+答案: Anith文章中的数字没有很好的标注 - 我认为图1图2都是糟糕设计的例子,而图2是好的设计.P,在那里担心了一会儿.

综上所述:

  • 查找表:.
  • 通用查找表:不好.

我将在下面提出我的问题以供参考.


给出以下原因:

  1. "你失去了确保准确数据的手段;约束.通过将不同的实体组合到一个表中,你没有声明方法来约束某个类别的值."
    限制价值如何失去准确性?

  2. "您必须将每种数据类型表示为具有此类通用查找表的字符串."
    如果我想表示另一种数据类型,我可以在其查找表中添加一列.

  3. "你致力于坚强和随后的复杂性."
    怎么样?

  4. 第四,也是最后,您面临着物理实现问题.
    我不明白为什么.

我不同意给出的大多数理由,并希望对我的错误进行一些客观的批评?逻辑.

我的例子:

引用维修服务中的工作示例,其中包含许多可能具有自然流动的可能状态,让我们采取一个JobStatus表格:

  1. 预订
  2. 分配给技师
  3. 诊断问题
  4. 等待客户确认
  5. 修理并准备好接送
  6. 修理和Couriered
  7. 无法弥补并准备好接送
  8. 引用被拒绝

可以说,这些状态中的一些可以标准化为表格Couriered Items,Completed Jobs并且Quotes(具有待定/接受/拒绝状态),但这感觉就像不必要的模式复杂化.

另一个常见示例是OrderStatus限制订单状态的表:

  1. 有待
  2. 已完成
  3. 取消
  4. 退款

状态标题和描述在一个地方进行编辑,并且易于作为带有外键的下拉列表用于动态数据应用程序.这对我来说过去很有用.如果业务规则规定了新订单状态的创建,我可以将其添加到OrderStatus表中,而无需重建我的代码.

为什么这是一个不好的做法?


编辑:我在我的问题中加入了Anith的理由,并试图保持客观.

-

APC*_*APC 12

Anith Sen建议反对的是所有查找代码都有一个查找表.这是category他的例子中的专栏的意义.每个类别都有一个单独的表是绝对可行的方法.

这是因为:

  1. 我们可以使用查找表通过强制外键来限制值
  2. 它使数据库更容易优化使用查找表连接数据表的查询
  3. 它可以更好地扩展:一个大的查找类别可以真正扭曲性能

在您的示例中,JobStatus和OrderStatus是单独的类别.适用于单独的实体.这就是为什么他们需要不同的查找表.在几个不同的数据表中共享相同的代码表甚至没有问题.当问题出现时,我们有一些单独的数据表(实体),其中某些状态是不合适的:这是将代码拆分成单独的查找表的时间.

编辑

我看到你编辑了你的帖子,引用了所有Anith的观点.我认为最重要的一点是关于约束的第一点.如果要将ORDERS.STATUS列限制为具有OrderStatus类别中的值,则必须使用单独的表来强制执行外键.您的替代方案是:

  • 在ORDERS表上包含一个CodeCategory列,并对公共CODES表强制执行复合外键,该表现在需要一个唯一的键(Category,Code).
  • 在检查约束中复制OrderStatus值
  • 不强制执行数据库中的值,并依赖应用程序的下拉列表来限制值.

从数据库的角度来看,所有这些选项都很糟糕.


Wal*_*tty 8

你已经有了正确的答案,所以这句话是额外的.

OTLT(一个真正的查找表)的一个大问题是,您最终将来自不同域的值放在同一列中,然后使用单独的列来消除歧义.

在您的示例中,您使用了每个状态描述旁边的数字.如果这些数字是数字代码,我认为它们必须是,那么你不希望值4,意思是"等待客户确认"在与值4相同的列中,意思是"已取消".如果您这样做,那么您不能将此列用作您的一个真实查找表的PK.

如果你给你的一个真正的查找表另一列,称之为"CodeType"并使用"CodeType"和"Code"作为复合PK,你通过为每个代码类型设置一个单独的查找表,引入了比你介绍的更多的复杂性.

简短的回答是:不要将来自不同域的值放在同一列中.它总是比它节省更多的麻烦.

顺便说一句,可以创建一个视图,将所有单独的查找表组合成一个看似单个巨型查找表的视图.这在某些非常特殊的情况下非常有用.

  • 给反模式命名的+1 - OTLT - 可搜索;) (3认同)