Pregunta

¿Hay alguna forma de comparar dos máscaras de bits en Transact-SQL para ver si alguno de los bits coincide? Tengo una tabla de usuario con una máscara de bits para todas las funciones a las que pertenece el usuario, y me gustaría seleccionar a todos los usuarios que tengan cualquiera de las funciones en la máscara de bits suministrada. Entonces, usando los datos a continuación, una máscara de bits de roles de 6 (diseñador + programador) debe seleccionar a Dave, Charlie y Susan, pero no a 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

¿Alguna idea? Gracias.

¿Fue útil?

Solución

La respuesta a su pregunta es usar el & amp; de Bitwise de esta manera:

SELECT * FROM UserTable WHERE Roles & 6 != 0

El 6 puede intercambiarse por cualquier combinación de su campo de bits donde desee verificar que cualquier usuario tenga uno o más de esos bits. Cuando trato de validar esto, por lo general me resulta útil escribir esto a largo plazo en binario. Su tabla de usuario se ve así:

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

Tu prueba (6) es esta

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

Si pasamos por cada persona que hace el bitwise y contra la prueba obtenemos lo siguiente:

        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) 

Lo anterior debe demostrar que cualquier registro donde el resultado no sea cero tiene uno o más de los indicadores solicitados.

Editar: Este es el caso de prueba en caso de que quieras revisar esto

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

o

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

o

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

Otros consejos

Use el bitwise AND operator de Transact-SQL " & amp ; " y compara el resultado a cero. Aún mejor, en lugar de codificar los roles como bits de una columna entera, use columnas booleanas, una para cada rol. Entonces su consulta sería simplemente amigable con el diseñador y el programador. Si espera que los roles cambien mucho a lo largo de la vida útil de su aplicación, use una tabla de muchos a muchos para asignar la asociación entre los usuarios y sus roles. ambas alternativas son más portátiles que depender de la existencia del operador AND a nivel de bit.

SELECT * FROM UserTable WHERE Roles & 6 > 0

SELECCIONA * DESDE la tabla WHERE mask1 & amp; máscara2 > 0

ejemplo:

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 encontrar todos los programadores usa:

SELECT * FROM UserTable WHERE Roles & 2 = 2
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top