Разборка перечисления битовых флагов в SQL Server - PullRequest
10 голосов
/ 27 января 2012

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

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

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

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

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

Ответы [ 2 ]

21 голосов
/ 27 января 2012

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

Чтобы включить бит 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)

14 голосов
/ 27 января 2012
SELECT * FROM first_table f 
  JOIN second_table s ON s.ID & f.Flags <> 0 
  WHERE f.something = something

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...