【问题标题】:Lookup tables implementation - one table or separate tables [closed]查找表实现 - 一个表或单独的表[关闭]
【发布时间】:2016-03-12 17:03:55
【问题描述】:

我将在一个系统中实现几个查找表。通常,所有查找表都具有相同的结构,例如 id, name, value, rank, active

我们在这个项目中使用 AngularJS 作为前端和 Web API/Entity 框架作为后端

我有一些选择

选项 1 - 创建一组具有相同结构的查找表 例如LKRegion、LKStatus、LKPeriod、LKState、LKDepartment等 此选项是传统设计。数据模式是结构化的且易于理解。很容易实现/强制执行外键完整性。但是您必须创建单独的 Web 方法来处理 CRUD 操作。如果将来要添加另一个查找表,则必须重复相同的操作。

选项 2 - 通过添加一个名为 LookupType 的额外列来标识查找组来创建一个大查找表 此选项减少了表的数量。使查找表易于维护和检索(例如,一种模式、一种 Web 方法可以处理所有常规查找 CRUD 操作)。但是由于 LookupType,外键完整性有点松散。

请分享您的偏好并告诉我原因。我想获得有关此实施的最佳实践。谢谢!

【问题讨论】:

  • 选项 2) 没有任何优势,从我的角度来看,丢失正确的外键是一个障碍。 “减少表的数量”没有意义。它不会使您的数据库更快或更小或更易于维护(实际上它会更难维护:如果您需要为一种查找类型添加新属性怎么办?然后为另一种查找类型添加另一个属性?)。选项 2 被称为 anti 模式“一个真正的查找表”
  • 如果我的查找表只是用于提供下拉列表文本/值,我以后可能不需要额外的属性,所以我将忽略属性维护的缺点。我对选项 1 的担忧是,如果我需要实现一个新的查找表,我需要拖动新的数据模式并重新编译项目。对于选项 2,它只是一个数据更改。如果考虑将项目从开发推广到生产,并且在同一个项目中进行了许多开发,并且有些还没有准备好上线,那么选项 2 更合适,风险也更小。
  • @RayGao,在设计数据库时,数据完整性比 CRUD 操作的易用性更重要。通常,数据的寿命比为该数据提供用户界面的应用程序的寿命长得多。 10 年后将会有另一个新的闪亮框架,新的应届毕业生将在任何地方使用它们,但业务将继续使用积累的数据,重要的是数据保持有效和正确。这就是为什么在数据库级别而不是在应用程序级别强制执行诸如外键之类的约束很重要的原因。
  • 如果您添加一个新的查找表,该表将被一些 other 表使用 - 这很可能也是新的。因此,无论如何您都需要推出新版本的应用程序(添加未使用的新查找表有什么意义)。您可能现在看不到扩展这些表的必要性,但您确定一年内没有一个吗?还是两年?重要数据的寿命比应用程序长很多。很多时候,应用程序被重新设计,但保留旧数据。稍后修复错误的数据模型比从一开始就以正确的方式修复要复杂得多。
  • 关于“我可能不需要额外的属性”——即使你说“我永远不需要额外的属性”,无论如何这会在一年左右的时间内改变:)

标签: sql database asp.net-web-api


【解决方案1】:

我会为选项 2 辩护,但一般来说,您需要选项 1。正如其他人所提到的,选项 1 是更简单的方法,并且很容易允许外键关系。

在某些情况下,使用单个参考表很方便。例如,如果您正在编写一个支持多种人类语言的系统,那么拥有一个包含事物名称的参考表比遍布整个数据库的无数参考表要简单得多。或者,我想,您可能有非常神秘的安全要求,需要复杂的加密算法——而且处理单个表更容易。

尽管如此,引用表的引用完整性很重要。一些数据库具有非基于触发器的机制,将支持一个表的引用完整性(Oracle 和 SQL Server 中的外键和计算列)。这些机制有点麻烦,但它们确实允许对单个表进行不同的外键引用。而且,您始终可以使用触发器来强制执行参照完整性,尽管我不推荐这种方法。

与数据库所做的大多数事情一样,没有正确的答案。有一个普遍接受的答案在大多数情况下有效/正确(选项 1)。第二个选项仅在有限的情况下是可取的,具体取决于系统要求。

【讨论】:

    【解决方案2】:

    我建议:

    A.如果这是一个企业系统,请遵循组织标准(我知道有些人可能会对此大笑)。如果存在这样的事情,它肯定会促进个别表。

    B.如果必须,仅将枚举或 1 个聚合查找表用于编程级别的查找(例如错误消息等)。任何业务相关数据的查找数据都应该(在我看来)在一个单独的表中,至少出于以下原因:

    1. 当您有单独的表时,您需要在连接时使用正确的表名,而不是使用引用表的代码列。这使得编写查询不太容易出错。编写“Select ... Where (TableID=12 and State="NY") AND (TableId=133 and Country="USA")”...编码风格在开发过程中很容易出错。从编码的角度来看,这是我的主要问题。

    2. 当插入或更新行中的引用多于 1 时,插入和更新的 RI 错误可能不明确。

    3. 在某些情况下,查找表可能具有自引用(关系)。例如,地理位置可以描述为层次结构,这会给模型增加更多混乱。

    4. 关系(引用)可能会在您的数据库中失去意义。您会发现系统中的几乎每个表都链接到这个表。它有些没有意义。

    5. 如果您曾经决定允许用户执行临时报告,那么他们将很难使用查找表的代码而不是名称。

    6. 我觉得 1 表方法破坏了规范化概念 - 但现在无法证明。

    一个缺点是,您可能需要为部分(或全部)单独的表在 PK 和 FK 上建立索引。但是,在当今可用的强大数据库的世界中,这可能不是什么大问题。

    在回答您的问题之前,我应该阅读网络上的大量讨论,但是如果您想自己看一下,我会提供一些链接:

    Link 1Link 2Link 3Link 4Link 5...

    【讨论】:

      【解决方案3】:

      不惜一切代价避免选项 2,选择选项 1甚至想都不想。(*)

      参照完整性太重要了,不能为了支持几乎任何其他问题而妥协。

      如果你去了,你会发现只有痛苦。

      如果您想减少重复,请使用您的 web-api 实现语言(java?)实现一个服务列表,并使用要使用的查找表的名称对每个服务进行参数化。

      编辑

      (*) 代表我说“想都没想”是错误的。当然,考虑一下。如果需要,请继续,甚至在 stackoverflow 上发布一个关于它的问题。思考是好的,上面 Gordon Linoff 的回答很好地证明了这一点。

      【讨论】:

      • @usr 我不确定这些是 enum 查找表,我不确定他还有其他选择,因为 OP 提到了“CRUD 操作”。跨度>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      • 2014-07-27
      • 1970-01-01
      • 1970-01-01
      • 2016-07-24
      • 2010-10-10
      • 2016-08-31
      相关资源
      最近更新 更多