【问题标题】:How to handle a lot of flags for a SQL record如何处理 SQL 记录的大量标志
【发布时间】:2010-09-14 14:00:55
【问题描述】:

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

两个问题,请多多包涵:)

假设我要为一条记录存储 20 个标志。

例如:

CanRead = 0x1 可写 = 0x2 可以修改 = 0x4 ... 以此类推到最后的标志 2^20

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

我可以通过 WHERE (Permissions & CanRead) = CanRead 轻松检查该记录是否需要权限

这行得通。

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

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

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

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

感谢您的帮助

【问题讨论】:

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


    【解决方案1】:

    我假设您的 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(二进制)。

    首先,让我们针对 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 操作的结果是 value = 0,那么测试的权限都不会应用于该行。如果该值大于 0,则至少存在一行。

    【讨论】:

      【解决方案2】:

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

      为每个标志使用一个布尔(位)值。在这个特定的示例中,您会发现可以读取、写入或修改的所有内容:

      WHERE CanRead AND (CanWrite OR CanModify)
      

      没有巧妙技巧的简单纯 SQL。您为每个标志浪费的额外 7 位不值得头疼。

      【讨论】:

      • 他们是如果,正如海报所建议的那样,每个字段只有一位。
      • 以这个简单的 where 子句为例,它是处理位值时所需要的。我的意图不是重现特定查询。
      • 绝对正确。说得好。使用数据库的力量! @Bill...逻辑运算是提问者所需要的——他只是在谈论按位运算,因为这是一个常见的(旧的)解决方案。
      • 在存储方面仅供参考,bit 列确实占用 1 位。例如,如果您有 8 位列,它将占用该记录中的 1 个字节。 msdn.microsoft.com/en-us/library/ms177603(v=sql.100).aspx
      • @tia:很高兴知道。因此,对字节字段进行按位运算的理由就更少了。
      【解决方案3】:

      怎么样

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

      ?

      【讨论】:

        【解决方案4】:

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

        我认为

        【讨论】:

          【解决方案5】:

          是不是很简单……

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

          ...因为任何 'bit' 设置为 1 都会导致 '&' 运算符的非零值。

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

          【讨论】:

            【解决方案6】:

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

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

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

            --更新--

            原来的查询写成

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

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

            【讨论】:

              【解决方案7】:

              不,这行不通。

              我只向程序发送一个掩码

              像@filter 这样的东西,在C# 中我用@filter = CanModify | 填充。会写

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

              哦,顺便说一下,这不是权限模型,我只是将其用作示例。

              我的对象确实有大约 20 个独特的标志。

              【讨论】:

                【解决方案8】:

                仅当您还使用其他键进行查询时才执行此操作。

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

                【讨论】:

                  猜你喜欢
                  • 2013-07-20
                  • 1970-01-01
                  • 2011-03-05
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-10-29
                  • 2018-07-31
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多