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

时间:2020-03-06 14:59:07  来源:igfitidea点击:

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

两个问题,请忍受我:)

假设我要存储20个标志,以用于一条记录。

例如:

CanRead = 0x1
CanWrite = 0x2
CanModify = 0x4
...
依此类推,直到最后一个标志2 ^ 20

现在,如果我设置一条记录的以下组合:权限= CanRead |可以写

我可以通过执行WHERE(Permissions&CanRead)= CanRead轻松检查该记录是否具有必需的权限

那个有效。

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

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

换句话说,如何找到与要发送到该过程的掩码中的任何标志匹配的记录?

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

谢谢你的帮助

解决方案

关于什么

WHERE (Permissions & CanWrite) = CanWrite 
OR (Permissions & CanModify) = CanModify

WHERE(权限和CanWrite)= CanWrite
OR(权限和CanModify)= CanModify

我认为

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

20个标志向我表明需要重新考虑,大多数文件系统可以通过12个基本标志来实现,ACLS可能具有单独的表,该表仅授予许可,或者对对象或者访问器进行分组以允许不同的控制。

我希望选择一个更快,有20个单独的字段,但我也不会添加20个字段来提高性能。

  • 更新 -

原始查询写为

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

就足够了,但是听起来好像我们在数据库中拥有的是实体可以拥有的一组属性。在这种情况下,唯一明智的方式(以数据库术语而言)是与属性表建立一对多关系。

不,那是行不通的。

我只给手术发一个口罩

类似@filter的东西,在Ci中用@filter = CanModify |可以写

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

哦,顺便说一句,它不是权限模型,我仅以它为例。

我确实有大约20个唯一标志,我的对象可以拥有。

它不像...那么简单吗?

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

...由于将任何"位"设置为1,将导致"&"运算符的值非零。

天已经很晚了,我要回家了,所以我的大脑可能工作效率低下了。

不要那样这就像将CSV字符串保存到备注字段中,并且破坏了数据库的用途。

为每个标志使用布尔值(位)。在此特定示例中,我们将找到可以读取,可以编写或者修改的所有内容:

WHERE CanRead AND (CanWrite OR CanModify)

简单的纯SQL,没有聪明的技巧。我们为每个标志浪费的额外7位不值得头疼。

我假设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。如果匹配1个或者多个条件,则结果将大于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(二进制)。

首先,让我们针对仅读取的表中的一行进行测试。

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,则至少存在一行。

仅当我们还通过其他键查询时,才执行此操作。

如果要通过标志组合进行查询,请不要执行此操作。对该列的索引通常对我们没有帮助。我们将只能进行表格扫描。