Разборка перечислений битовых флагов в SQL Server

у меня есть INT столбец в базе данных SQL Server, в котором хранится значение, относящееся к перечислению битовых флагов. Например, если перечисление:

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

столбец в SQL Server может содержать значение 5.

что мне нужно сделать, это выбрать все строки из другой таблицы, содержащей дополнительные сведения о UserType, поэтому, используя пример значения 5, я хотел бы выбрать строки из второй таблицы с идентификаторами 1 и 4.

кто-нибудь знайте умный способ разбить число таким образом-в идеале метод должен быть рекурсивным в некоторой степени, так как это очень упрощенный пример, а фактические таблицы/перечисления намного больше.

2 ответов


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

это выделит все строки из second_table, которые соответствуют любому из флагов в данной строке в первой таблице.


чтобы получить все строки, для которых верно, что 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 содержит флаги и пользователи должны иметь все set:

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

где PermissionSets содержит флаги и пользователи должны иметь один set:

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

включить SuperUser бит для пользователя с идентификатором 93

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

выключить SuperUser бит для пользователя с идентификатором 93

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

от ADO.NET (или что-то еще) код, который используется для борьбы с этим из C#, мы можем передать соответствующий UserType значение, приведенное к int в параметр, а не отправка 4 или 5 явно.

Edit: см. также,побитовые операторы (Transact-SQL)