operadores campo bitwise sql sql-server tsql bitmask

campo - operadores bitwise sql server



Comparando dos máscaras de bits en SQL para ver si alguno de los bits coincide (6)

Para encontrar todos los programadores use:

SELECT * FROM UserTable WHERE Roles & 2 = 2

¿Hay alguna manera 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 todos los usuarios que tienen cualquiera de los roles en la máscara de bits proporcionada. Entonces, usando los datos a continuación, una máscara de bits 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

¿Algunas ideas? Gracias.


SELECCIONAR * FROM tabla DONDE mask1 y mask2> 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


La respuesta a su pregunta es usar Bitwise & así:

SELECT * FROM UserTable WHERE Roles & 6 != 0

El 6 se puede intercambiar por cualquier combinación de su campo de bits donde quiera verificar que cualquier usuario tenga uno o más de esos bits. Al intentar validar esto, generalmente me resulta útil escribir esto a mano 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

Su prueba (6) es esta

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

Si examinamos a cada persona haciendo el bitwaise Y en contra de la prueba obtenemos esto:

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 es cero tiene uno o más de los indicadores solicitados.

Editar: Aquí está el caso de prueba si desea verificar 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


SELECT * FROM UserTable WHERE Roles & 6 > 0


Use el operador Y de Transact-SQL en bits "&" y compare el resultado con 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 de su aplicación, utilice una tabla de muchos a muchos para mapear la asociación entre los usuarios y sus roles. Ambas alternativas son más portátiles que confiar en la existencia del operador Y a nivel de bit.