Разбор бит-флагов в SQL Server

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

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

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

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

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

Ответ 1

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

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

Ответ 2

Чтобы получить все строки, для которых это верно, и то, что установлено 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

Или присоединение к флагам. Где PermissionSet содержит флаги, а пользователи должны иметь все:

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

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

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

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

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

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

Изменить: см. также Побитовые операторы (Transact-SQL)