11

RDBMS 中的适当规范化意味着表的增殖。整数字段可以将正交数据存储为位——这可以用作附加表的替代品,而不牺牲关系完整性吗?

4

3 回答 3

10

对于一对多关系,其中“多”具有少量已知值,可以将关系作为位掩码作为整数存储在父表中,从而无需额外的表。

假设我们有一张桌子 Person,我们想知道一个人访问过多少个大陆。我们首先为每个大陆分配一个“正交”位值。在 C# 中,枚举是一个不错的选择:

[Flags]
public enum JobAdvertisingRegion
{
    NorthAmerica = 1,              // or 1 << 0
    SouthAmerica = 2,              // 1 << 1
    Europe = 4,                    // 1 << 2
    Asia = 8,                      // 1 << 3
    Africa = = 16,                 // 1 << 4
    Australia = 32,                // 1 << 5
    Anarctica = 64                 // 1 << 6
}

Persons 表可以简单地有一个称为 Contintents 的 int 列。表示一个人访问过欧洲和亚洲:

UPDATE Persons SET Continents = (4 + 8) WHERE Id = whatever

要搜索访问过南极洲的人,我们使用按位数学:

SELECT * FROM Persons WHERE Continents & 64 = 64

要搜索访问过非洲和亚洲的人员:

SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8)

要搜索访问过澳大利亚或南美的人:

SELECT * FROM Persons WHERE Continents & (32 + 2) != 0

一个缺点是,虽然整数列在 SQL 中是可索引的,但它们的位组件不是。对于上述查询,一些优化可以解决这个问题:

SELECT * FROM Persons WHERE Continents & 64 = 64 AND Continents >= 64

SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8) AND Continents >= (16 + 8)

SELECT * FROM Persons WHERE Continents & (32 + 2) != 0 AND Continents >= 2
于 2012-08-02T17:53:43.097 回答
7

你的问题的答案是“不”。位字段牺牲了关系完整性,原因很简单,数据库中的实体没有对应的表。

也就是说,许多数据库为此提供支持,通常是通过“位”数据类型。Mysql 具有更强的支持,具有“set”数据类型。

主要问题是您对集合中的元素一无所知——全名是什么,何时将其添加到数据库中,等等。(枚举解决了部分命名问题。)此外,集合的大小是有限的。你可能有一个例子,事情是有限的。然而,Matt 的例子更强调了这里的问题。您可以查看访问过的大陆列表。但是,当您切换到访问过的国家时,方法必然会大不相同,因为国家的数量不再适合单个“单词”。您是否希望您的系统在这方面以与国家截然不同的方式对待大陆?您是否希望您的设计决策受到计算机字中 32 位或 64 位的限制?

最后,您似乎将表格的激增视为一个问题。表的扩散实际上是一种解决方案。所有关于实体的数据都存储在表中,而不是通过系统分散。您可以维护有关实体实例的信息,例如创建实例的时间、它可能随时间发生的变化等。每当有人想要一个大陆时,都可能使用“大陆”的实体。

考虑在两个不同的开发人员决定为大陆开发自己的位掩码的系统中会发生什么——但他们将大陆按不同的顺序排列。使用设计良好的关系数据库(意味着在表定义中明确声明外键关系),就不会出现这种混淆。

于 2012-08-02T18:12:30.450 回答
1

好吧,我将通过简单地陈述一些事实来反对(当前)流行的观点

  • SQL 和关系模型不是一回事。
  • 关系模型(理论)适用于关系变量,即所谓的 relvars
  • SQL 数据库使用表。
  • 表和相关变量不一样,但可以——出于所有实际目的。
  • 要使用关系建模理论,表应该代表相关变量。
  • 对于表示关系变量的表,应满足以下条件:

    1. 行没有顺序
    2. 列没有顺序
    3. 没有重复的行
    4. 每个列-行交集只有一个列定义类型的值
    5. 没有特殊的隐藏列(行 ID、对象 ID ...)

因此,您可以使用超出关系设计理论范围的表和 SQL 做很多事情,但是您确实失去了“关系”的好处......

从技术上讲,您的帖子(问题)有两个答案。

  • 是的,到帖子的标题。
  • 不,到帖子的正文。
于 2012-08-02T19:16:07.467 回答