Разборка перечислений битовых флагов в 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)