2

我有一个基础实体(项目),它将承载具有完全不同属性的大量项目类型(> 200)。我想要一个干净的便携式和快速的解决方案,并且想出了一个想法,maby 有一个我不知道的名字。

它是这样的:

  • items-entity 包含基类字段 + 子类字段的附加字段,但具有虚拟名称、ItemID、ItemNo、ItemTypeID、int1、int2、dec1、dec2、dec3、str1、str2

  • 引用的 itemtype-record 包含类型名称和子实体 (1:n):

  • itemtypefields [itemtypeid,name,type,realfield] [53,MaxPressure,dec,dec3] 中的示例

它的局限性:

  • 难以估计基类中的现场要求
  • 更难根据子类型添加域/检查约束
  • 需要应用层将标记的 sql 转换为真正的查询
  • 一次只能查询一种类型,因为共享属性可能被定义为不同的“真实字段”。

第三条解释:

select ItemNo,_MaxPressure_ from items where ItemTypeID=10 and _MaxPressure_>42
should translate to:
select ItemNo,dec3 as MaxPressure from items where ItemType=10 and dec3>42

(不能用 sp 或 udf 的权利来做到这一点 - 或者有可能吗?)

但好处:

  • 表现
  • 易于 CRUD 操作
  • 更容易在应用程序级别进行排序/过滤。

现在 - 它有名字吗?

4

1 回答 1

8

这种反模式称为One True Lookup Table

在关系数据库中,每一列都需要定义为一种逻辑类型。我不是指像 INT 或 VARCHAR 这样的 SQL 数据类型,我的意思是该列中从头到尾的所有内容都必须来自同一组值,并且您应该能够将一个值与另一个值区分开来。

您不能将鞋码、平均温度和每英寸螺纹数放在给定表格的同一列中,仍然称其为关系。

基本上,您的数据库根本就不是数据库——而是电子表格

阅读 CJ Date 的几乎所有书籍,例如SQL 和 Relational Theory,以获得对关系和类型的正确解释。


回复您的评论:

在讲基本书籍和嘲笑半结构化数据之前,请再次阅读 Q。

好的,我重新看了你的帖子。

One True Lookup Table 的经典用法并不完全是您正在做的事情,但您正在做的事情与 OTLT 存在相同的问题。

假设您在 ItemType 10 的列中存储了“MaxPressure” dec3。假设 MaxPressure 的值有一组固定的有效选择,并且您希望将它们放在另一个查找表中,这样就没有人可以输入无效的 MaxPressure 值。

现在:在 dec3 上声明一个外键约束,引用您的 MaxPressures 查找表。你不能——问题是外键约束适用于所有行中的 dec3 列,而不仅仅是那些 ItemType 为 10 的行。

原因是您在单个列中存储了多个值。任何其他类型的约束都会出现同样的问题——唯一约束、检查约束,甚至 NOT NULL。而且您也不能为该列声明 DEFAULT 值,因为您可能对每个 ItemType 有不同的正确默认值(并且某些 ItemTypes 没有该属性的默认值)。

我提到 CJ Date book 的原因是他对类型给出了清晰的定义:它是一个命名的有限集,在其上定义了相等操作。也就是说,您可以判断一行上的值“42”是否与另一行上的值“42”相同。在关系列中,这必须是正确的,因为它们必须来自相同的原始值集。在您的表中,dec3当它是 MaxPressure 时可能具有值“42”,而当它是每英寸线程数时,另一个 ItemType 可能具有值“42”。因此它们不是相同的值“42”。如果您有唯一约束,则这两个 42 不会被视为重复。如果你有一个外键,每个不同的 42 都会引用一个不同的查找表,等等。

您所做的不是有效的关系数据库设计。

除非您明白这一点,否则不要因为我向您推荐关系数据库设计资源而生气。

于 2013-03-21T00:07:43.303 回答