可以将按位数学用于SQL中的一对多关系吗?

Mat*_*man 11 c# sql enums bit-manipulation

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

Mat*_*man 10

对于一对多的关系,其中"多"具有小数目的已知值的,关系可以被存储为在父表为一个整数位掩码,替换为另一个表的需要.

假设我们有一个表人员,我们想知道一个人访问了多少个大陆.我们首先为每个大陆分配一个"正交"比特值.在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
}
Run Code Online (Sandbox Code Playgroud)

然后,Persons表可以只有一个名为Contintents的int列.表明某人已访问过欧洲和亚洲:

UPDATE Persons SET Continents = (4 + 8) WHERE Id = whatever
Run Code Online (Sandbox Code Playgroud)

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

SELECT * FROM Persons WHERE Continents & 64 = 64
Run Code Online (Sandbox Code Playgroud)

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

SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8)
Run Code Online (Sandbox Code Playgroud)

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

SELECT * FROM Persons WHERE Continents & (32 + 2) != 0
Run Code Online (Sandbox Code Playgroud)

一个缺点是,虽然整数列在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
Run Code Online (Sandbox Code Playgroud)

  • -1违反1NF,在便宜的TB级驱动器时代优化空间,不扩展到超过64个区域,使用二进制数学反模式 (7认同)

Gor*_*off 7

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

也就是说,许多数据库通常通过"位"数据类型提供支持.Mysql具有更强大的支持,具有"set"数据类型.

主要问题是您对集合中的元素一无所知 - 全名是什么,何时添加到数据库中,等等.(枚举可以解决部分命名问题.)此外,集合的大小也是有限的.你可能有一个事物有限的例子.然而,马特的例子相当强调了这里的问题.您可以列出访问过的各大洲.但是,当您切换到访问过的国家时,方法必然会有很大不同,因为国家/地区的数量不再适用于单个"单词".您是否希望您的系统在这方面与各国的处理方式截然不同?您是否希望您的设计决策受到计算机字中32或64位的限制?

最后,您似乎将表的扩散视为一个问题.表的扩散实际上是一种解决方案.有关实体的所有数据都存储在表中,而不是通过系统传播.您可以维护有关实体实例的信息,例如创建实例的时间,实例可能随时间的变化情况等等.只要有人想要一个大陆,就可能会使用"大陆"的实体.

考虑一下系统中发生了什么,两个不同的开发人员决定为各大洲开发自己的位掩码 - 但他们将各大洲的顺序排在不同的位置.使用设计良好的关系数据库(意味着在表定义中显式声明了外键关系),不会出现这种混淆.