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

问题描述:

以下情景:您在C#中有几个与SQL Server中的Enum-ish表绑定(实际上由其生成)的标志枚举。假设您是分销商,并且您允许您的分销商指定他们运送到的美国州。作为一个辉煌和优雅的软件工程师,你实施这些为按位组合的标志值,以节省存储:使用64位有符号值在SQL和C#中模拟128位无符号整数?

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枚举。

+1

组合是的,但在这种情况下,组合就像向印第安那州和加利福尼亚州运送,而不是一个州。无论如何,也许你可以尝试使用GUID?它们实际上是128位整数。 – kubal5003 2009-11-14 00:46:17

+1

负性空间只是64位中的一个,所以没有。 – Joe 2009-11-14 01:45:48

+1

我遇到了完全相同的问题。你如何使用GUID来存储数字? – arao6 2014-10-28 02:55:48

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

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

这给了你38位到小数点(1E38)的左侧。在二进制方面,它大约是126位(8.5E37)。它可以像一个数字一样操纵。

但是,一种选择是定义你想要的.NET,并在SQL Server中使用匹配的CLR data type。这样,它可以在两个平台之间保持一致。

不过,我真的会考虑改变从标志了......

+0

不幸的是,对于按位运算符,十进制类型无效。 CLR数据类型的想法很有趣,我将调查我是否可以用这个角度拉出> 64位的标志。至于远离标志的情况,我通常只在预期存在十几个或更少的可能值的地方使用它们,并且没有其他理由来创建多对多关系。我也有一个工具可以在SQL端自动生成可索引查询,而在.NET端为它们包含运算符,但是我将它们的使用限制在可能节省空间和编码时间的实例中。 – 2009-11-15 04:51:31

我2C:你想聪明,和你造成你自己的痛苦。位域和SQL混合不好,主要是因为位域无法正确编制索引,并且任何搜索都必须执行完整扫描。例如。找到所有发送给AK的经销商,您需要扫描整个经销商的表格。此外,该解决方案不会扩展到超过64个值(如您已经发现的)。它也是不好的存储选择,它需要一些值为0来存储负面信息(缺乏关联)。

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

+0

采取了点。关于索引虽然,搜索do * not *需要在经销商表上进行表扫描。在64行最大状态表上有一个扫描来构建索引的@StateIDs表变量,该变量包含所有按位比较的输出。 (这项工作实际上也可以持久化,但这并不足以影响到这一点)。@StateIDs表var随后通过值连接到经销商表的外键以检索没有表扫描的匹配项。 – 2009-11-14 20:31:14