Pergunta

Existe uma maneira de comparar dois bitmasks em Transact-SQL para ver se algum dos bits combinar? Eu tenho uma tabela de usuário com uma máscara de bits para todos os papéis o usuário pertence, e eu gostaria de selecionar todos os usuários que têm qualquer dos papéis na bitmask fornecido. Então, usando os dados a seguir, um papel máscara de bits 6 (designer + programador) deve selecionar Dave, Charlie e Susan, mas não Nick.

User Table
----------
ID  Username  Roles
1   Dave      6
2   Charlie   2
3   Susan     4
4   Nick      1

Roles Table
-----------
ID  Role
1   Admin
2   Programmer
4   Designer

Todas as idéias? Obrigado.

Foi útil?

Solução

A resposta à sua pergunta é usar o & Bitwise assim:

SELECT * FROM UserTable WHERE Roles & 6 != 0

O 6 pode ser trocado por qualquer combinação de seu bitfield onde você quiser verificar que qualquer usuário tem um ou mais desses bits. Ao tentar validar esta Eu costumo achar que é útil para escrever este fora escrita comum em binário. Sua tabela de usuário olha como este:

        1   2   4
------------------
Dave    0   1   1
Charlie 0   1   0
Susan   0   0   1   
Nick    1   0   0

Seu teste (6) é este

        1   2   4
------------------
Test    0   1   1

Se passar por cada pessoa que faz a bitwaise e contra o teste obtemos estes:

        1   2   4
------------------
Dave    0   1   1   
Test    0   1   1
Result  0   1   1 (6)

Charlie 0   1   0
Test    0   1   1
Result  0   1   0 (2)

Susan   0   0   1
Test    0   1   1
Result  0   0   1 (4)

Nick    1   0   0
Test    0   1   1
Result  0   0   0 (0) 

O acima deve demonstrar que os registros onde o resultado não é zero tem uma ou mais das bandeiras solicitados.

Edit: Aqui está o caso de teste você deve querer verificar este

with test (id, username, roles)
AS
(
    SELECT 1,'Dave',6
    UNION SELECT 2,'Charlie',2
    UNION SELECT 3,'Susan',4
    UNION SELECT 4,'Nick',1
)
select * from test where (roles & 6) != 0  // returns dave, charlie & susan

ou

select * from test where (roles & 2) != 0 // returns Dave & Charlie

ou

select * from test where (roles & 7) != 0 // returns dave, charlie, susan & nick

Outras dicas

Use o Transact-SQL bit a bit operador AND "&" e comparar o resultado a zero. Ainda melhor, em vez de codificar as funções como bits de uma coluna de número inteiro, utilizar colunas booleanos, uma para cada função. Em seguida, sua consulta seria simplesmente desenhador e programador amigável. Se você espera que os papéis de mudar muito ao longo do tempo de vida de sua aplicação, em seguida, usar uma tabela de muitos-para-muitos para mapear a associação entre os usuários e seus papéis. Ambas as alternativas são mais portáteis do que confiar na existência do bit a bit E operador.

SELECT * FROM UserTable WHERE Roles & 6 > 0

* SELECT FROM tabela WHERE mask1 & mask2> 0

exemplo:

DECLARE @Mask int
SET @Mask = 6

DECLARE @Users TABLE
(
ID int,
Username varchar(50),
Roles int
)

INSERT INTO @Users (ID, Username, Roles) 
SELECT 1, 'Dave', 6
UNION
SELECT 2, 'Charlie', 2
UNION
SELECT 3, 'Susan', 4
UNION
SELECT 4, 'Nick', 1

SELECT * FROM @Users WHERE Roles & @Mask > 0

Para todos os programadores usar:

SELECT * FROM UserTable WHERE Roles & 2 = 2
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top