使用64位有符号值在SQL和C#中模拟128位无符号整数?

采取这种情况:您在C#中绑定了一些标记枚举(实际上是从SQL Server中的Enum-ish表生成)。 假设您是经销商,并允许您的经销商指定他们发货的美国州。 作为一名出色而优雅的软件工程师,您将这些作为可按位组合的标志值实现以节省存储:

create table USState ( StateID bigint, StateAbbr char(2), StateName varchar(50)) /* insert all US States + DC into USState, StateIDs must be in powers of two */ /* StateID 0 reserved for 'None': */ create procedure GetStatesByFlag (@StateFlags bigint) as declare @StateIDs table ( StateID bigint, primary key (StateID) ) insert into @StateIDs select StateID from USState where @StateFlags & StateID != 0 or (@StateFlags = 0 and StateID = 0) select s.StateID, s.StateAbbr, s.StateName from USState s join @StateIDs si on si.StateID = s.StateID 

甜。 您可以使用按位逻辑在SQL和C#中动态包含/排除,这使您可以立即在Asp.NET中包含复选框列表和选择列表,同时仍然只存储一个64位数字来保存任何选择组合。 并且在过程的WHERE子句中不需要非可索引的比较运算符,除了最多包含64行的枚举表本身。 在经销商处搜索运往印第安纳州和加利福尼亚州的所有人仍然可以使用相等比较和索引。

现在您要求增加对美国领土,武装部队邮政编码和加拿大各省的支持,并以向后兼容的方式进行。 没有将名单减少到<64个条目,并且企业真的希望避免将老派国家与其他地区和部门分开。

你是做什么?

很有创意的答案,但真正的挑战是这样的:有没有办法强制使用相同的按位数学运算无符号64位值来处理有符号数,同时使用负空间超过64位可能位,在C#中和SQL(2008)? 如果重要,则模拟标志,而不是“真实”标志,因此从技术上讲,不需要使用[Flags]属性来对抗CLR枚举。

64位值不能超过64位,甚至不能使用“负空间”。 如果你有64位,你有64位。 您可以使用Guid获取128位,这会将问题关闭一段时间,但最终您需要添加其他字段。

在SQL Server中,您可以尝试十进制(38,0)

这将给出小数点左边38位数字(1E38)。 用二进制表示,它大约是126位(8.5E37)。 它可以像数字一样被操纵。

但是,一种选择是在.NET中定义您想要的内容并在SQL Server中使用匹配的CLR数据类型 。 这样,它可以在两个平台之间保持一致。

但是,我真的会考虑改变旗帜……

我的2c:你想要聪明,你自己的痛苦。 Bitfields和SQL混合不好,主要是因为位域无法正确编入索引,任何搜索都必须进行全扫描。 例如。 要查找运送到AK的所有研究人员,您需要扫描整个研究人员表。 此解决方案也不会扩展到超过64个值(正如您已经发现的那样)。 它的存储选择也很差,它需要一点值0来存储负面信息(缺乏关联)。

使用单独的表格来模拟经销商与其运送到的州/地区/省/国家/地区之间的多对多关系。