正在SQL Server中分解位标志枚举

本文关键字:标志 枚举 分解 SQL Server 正在 | 更新日期: 2023-09-27 18:21:31

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

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

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

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

有人知道用这种方式分解数字的聪明方法吗?理想情况下,该方法应该在一定程度上是递归的,因为这是一个非常简化的例子,而且实际的表/枚举要大得多。

正在SQL Server中分解位标志枚举

要获取所有设置了1和4都为true的行。。。

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(或其他)代码中,我们可以将相关的UserType值强制转换为int值传递到参数中,而不是显式发送45

编辑:另请参阅位运算符(Transact-SQL)

SELECT * FROM first_table f 
  JOIN second_table s ON s.ID & f.Flags <> 0 
  WHERE f.something = something

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