如何处理SQL记录的很多标志

时间:2008-10-01 16:32:36

标签: sql sql-server-2008 bit-manipulation

我需要有关如何在SQL2k8表中处理相对较大的标志集的建议。

两个问题,请跟我说。)

假设我有20个标志,我想存储一个记录。

例如:

CanRead = 0x1 CanWrite = 0x2 CanModify = 0x4 ... 依此类推到最后的旗帜2 ^ 20

现在,如果我设置以下一条记录的组合:Permissions = CanRead | CanWrite

我可以通过WHERE(Permissions& CanRead)= CanRead

轻松检查该记录是否具有所需权限

有效。

但是,我还要检索所有可以写或修改的记录。

如果我发出WHERE(Permissions&(CanWrite | CanModify))=(CanWrite | CanModify)我显然不会得到我的权限设置为CanRead的记录CanWrite

换句话说,我怎样才能找到与我发送给程序的面具中的任何标志相匹配的记录?

第二个问题,SQL 2008中的性能如何?创建20位字段实际上会更好吗?

感谢您的帮助

8 个答案:

答案 0 :(得分:12)

我假设您的Permissions列是Int。如果是,我鼓励您使用我在下面提供的示例代码。这应该可以清楚地表明功能的工作原理。

Declare @Temp Table(Permission Int, PermissionType VarChar(20))

Declare @CanRead Int
Declare @CanWrite Int
Declare @CanModify Int

Select @CanRead = 1, @CanWrite = 2, @CanModify = 4

Insert Into @Temp Values(@CanRead | @CanWrite, 'Read,write')
Insert Into @Temp Values(@CanRead, 'Read')
Insert Into @Temp Values(@CanWrite, 'Write')
Insert Into @Temp Values(@CanModify | @CanWrite, 'Modify, write')
Insert Into @Temp Values(@CanModify, 'Modify')

Select * 
From   @Temp 
Where  Permission & (@CanRead | @CanWrite) > 0

Select * 
From   @Temp 
Where  Permission & (@CanRead | @CanModify) > 0

当您使用逻辑时,您将根据您的条件得到一个1的数字。如果没有匹配,则结果为0.如果一个或多个条件匹配,则结果将大于0.

让我举个例子。

假设CanRead = 1,CanWrite = 2,CanModify = 4.有效组合为:

Modify Write Read Permissions
------ ----- ---- -----------
  0       0    0   Nothing
  0       0    1   Read
  0       1    0   Write
  0       1    1   Read, Write
  1       0    0   Modify
  1       0    1   Modify, Read
  1       1    0   Modify, Write
  1       1    1   Modify, Write, Read

现在,假设您要测试“读取”或“修改”。从您的应用程序,您将传入(CanRead | CanModify)。这将是101(二进制)。

首先,让我们对ONLY已经读过的表中的一行进行测试。

   001 (Row from table)
&  101 (Permissions to test)
------
   001 (result is greater than 0)

现在,让我们测试一下只有Write的行。

   010 (Row from table)
&  101 (Permission to test)
------
   000 (result = 0)

现在对具有所有3个权限的行进行测试。

   111 (Row from table)
&  101 (Permission to test)
------
   101 (result is greater than 0)

我希望您可以看到,如果AND操作的结果导致值= 0,则所有测试的权限都不适用于该行。如果该值大于0,则至少存在一行。

答案 1 :(得分:11)

不要那样。这就像将CSV字符串保存到备忘录字段中并破坏了数据库的目的。

对每个标志使用布尔(位)值。在这个特定的样本中,您可以找到所有可以阅读并可以编写或修改的内容:

WHERE CanRead AND (CanWrite OR CanModify)

简单的纯SQL,没有聪明的黑客攻击。你为每一面旗帜浪费的额外7位不值得头疼。

答案 2 :(得分:6)

怎么样?
WHERE (Permissions & CanWrite) = CanWrite 
OR (Permissions & CanModify) = CanModify

答案 3 :(得分:3)

WHERE(Permissions& CanWrite)= CanWrite 或(权限和CanModify)= CanModify

我认为

答案 4 :(得分:3)

不是那么简单......

WHERE (Permissions & ( CanWrite | CanModify )) > 0

...因为任何'bit'被设置为1将导致'&'的非零值操作

现在已经很晚了,我准备回家了,所以我的大脑可能工作效率低下。

答案 5 :(得分:1)

拥有不同的权限模型会好得多。

20个标志会向我表明需要重新考虑,大多数文件系统可以使用12个基本标志和ACLS - 可能有一个单独的表只授予权限,或者分组对象或访问器以允许不同的控制。

我希望select可以更快地拥有20个单独的字段 - 但我也不会为性能添加20个字段。

- 更新 -

原始查询写为

 WHERE (Permissions & ( CanWrite | CanModify )) > 0

就足够了,但听起来好像你在数据库中拥有的是一组实体可以拥有的属性。在这种情况下,唯一明智的(在数据库方面)这样做的方式是与属性表的一对多关系。

答案 6 :(得分:0)

不,那不行。

我只向程序发送了一个掩码

像@filter这样的东西在C#中填充@filter = CanModify | CanWrite

因此,该过程将OR-ed值作为过滤器。

哦顺便说一句,它不是一个权限模型,我只是作为一个例子。

我的对象可以拥有大约20个独特的标志。

答案 7 :(得分:0)

只有在您通过其他密钥查询时才执行此操作。

如果要通过标志组合查询,请不要这样做。对此列的索引一般不会对您有所帮助。您将被限制为表扫描。