在SQL Server中反汇编标志枚举

时间:2012-01-27 11:58:49

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

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

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

然后SQL Server中的列可能保存值为5。

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

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

2 个答案:

答案 0 :(得分:21)

要获得设置为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

为身份为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传递给参数,而不是发送4或{{ 1}}明确。

修改:另请参阅Bitwise Operators (Transact-SQL)

答案 1 :(得分:14)

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

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