我出于好奇而问这个问题.基本上我的问题是当你有一个数据库需要一个行条目来做一些像旗帜一样的东西时,最佳做法是什么?一个很好的例子就是堆栈溢出上的徽章,或者bugzilla中的操作系统字段.可以为给定条目设置标志的任何子集.
通常,我做c和c ++工作,所以我的直觉反应是使用无符号整数字段作为一组可以翻转的位......但我知道这不是一个好的解决方案,原因有几个.其中最明显的是比例能力,我可以拥有多少旗帜的硬上限.
我还可以考虑其他几种解决方案,这些解决方案可以更好地扩展,但会出现性能问题,因为它们需要多次选择才能获得所有信息.
那么,做到这一点的"正确"方法是什么?
一般来说,我避免使用位掩码字段.它们将来很难阅读,它们需要更深入的数据知识才能理解.
之前已经提出了关系解决方案.根据您概述的示例,我将创建类似这样的内容(在SQL Server中):
CREATE TABLE Users ( UserId INT IDENTITY(1, 1) PRIMARY KEY, FirstName VARCHAR(50), LastName VARCHAR(50), EmailAddress VARCHAR(255) ); CREATE TABLE Badges ( BadgeId INT IDENTITY(1, 1) PRIMARY KEY, [Name] VARCHAR(50), [Description] VARCHAR(255) ); CREATE TABLE UserBadges ( UserId INT REFERENCES Users(UserId), BadgeId INT REFERENCES Badges(BadgeId) );
如果你确实需要一组封闭的标志中的无界选择(例如stackoverflow标记),那么"关系方式"将是创建一个标志表和一个单独的表,它将这些标志与你的目标实体联系起来.因此,用户,标志和usersToFlags.
但是,如果空间效率是一个严重的问题而查询能力不是,那么无符号掩码几乎也可以.
在许多情况下,它取决于很多东西 - 比如你的数据库后端.例如,如果您正在使用MySQL,则SET数据类型正是您想要的.
基本上,它只是一个位掩码,每个位都赋值.MySQL支持最多64位值(意味着64个不同的切换).如果你只需要8,那么每行只需要一个字节,这是相当可观的节省.
如果你真的在一个字段中拥有超过64个值,那么你的字段可能会变得更复杂.您可能希望扩展到BLOB数据类型,这只是MySQL没有固有理解的原始位集.使用它,您可以创建任意数量的位字段,MySQL很乐意将其视为二进制,十六进制或十进制值,但您需要.如果您需要超过64个选项,请创建适合您的应用程序的多个字段.缺点是难以使人类可读的领域.该BIT数据类型也被限制为64.