【问题标题】:Disassembling Bit Flag Enumerations in SQL Server在 SQL Server 中反汇编位标志枚举
【发布时间】:2023-03-28 17:14:01
【问题描述】:

我在 SQL Server 数据库中有一个 INT 列,该列存储与位标志枚举相关的值。例如,如果枚举是:

[Flags()]
public enum UserType
{
    StandardUser = 1,
    Admin = 2,
    SuperUser = 4
}

那么 SQL Server 中的列的值可能为 5。

我需要做的是从另一个表中选择所有行,其中包含有关UserType 的其他详细信息,因此使用值为 5 的示例,我想从第二个表中选择 ID 为 1 的行和 4.

有谁知道以这种方式分解数字的聪明方法 - 理想情况下,该方法应该在某种程度上是递归的,因为这是一个非常简化的示例,并且实际的表/枚举要大得多。

【问题讨论】:

    标签: c# .net sql-server sql-server-2008


    【解决方案1】:

    要获取设置为 1 和设置为 4 的所有行...

    SELECT * FROM UserTable
    WHERE userType & 5 = 5
    

    要获取至少设置了 1 或 4 之一的所有行...

    SELECT * FROM UserTable
    WHERE userType & 5 <> 0
    

    当然我们可以将它与连接结合起来:

    SELECT Projects.*
    FROM Projects JOIN UserTable
    ON userID = UserTable.id
    WHERE userType & 5 <> 0
    

    或者加入旗帜。其中 PermissionSets 包含标志并且用户必须全部设置:

    SELECT UserTable.*
    FROM UserTable JOIN PermissionSets
    ON UserTable.userType & PermissionSets.userType = PermissionSets.userType
    WHERE PermissionSets.id = 42
    

    其中 PermissionSets 包含标志且用户必须拥有一组:

    SELECT UserTable.*
    FROM UserTable JOIN PermissionSets
    ON UserTable.userType & PermissionSets.userType <> 0
    WHERE PermissionSets.id = 42
    

    为 id 为 93 的用户打开SuperUser 位

    UPDATE UserTable
    SET userType = userType | 4
    WHERE id = 93
    

    为 id 为 93 的用户关闭 SuperUser 位

    UPDATE UserTable
    SET userType = userType & ~4
    WHERE id = 93
    

    从用于从 C# 处理此问题的 ADO.NET(或其他)代码中,我们可以将转换为 int 的相关 UserType 值传递到参数中,而不是显式发送 4 或 5。

    编辑:另见Bitwise Operators (Transact-SQL)

    【讨论】:

    • 谢谢乔恩,超级解释
    【解决方案2】:
    SELECT * FROM first_table f 
      JOIN second_table s ON s.ID & f.Flags <> 0 
      WHERE f.something = something
    

    这将从 second_table 中选择与第一个表中给定行上的任何标志匹配的所有行。

    【讨论】:

      猜你喜欢
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多