Existe-t-il un moyen de comparer deux masques de bits dans Transact-SQL pour vérifier si l'un des bits correspond? J'ai une table utilisateur avec un masque de bits pour tous les rôles auxquels l'utilisateur appartient, et j'aimerais sélectionner tous les utilisateurs ayant aucun des rôles dans le masque de bits fourni. Donc, en utilisant les données ci-dessous, un masque de bits de rôles de 6 (concepteur + programmeur) devrait sélectionner Dave, Charlie et Susan, mais pas Nick.
Table utilisateur ---------- ID Nom d'utilisateur Roles 1 Dave 6 2 Charlie 2 3 Susan 4 4 Nick 1 Roles Table ----------- ID Rôle 1 Administrateur 2 Programmeur 4 Concepteur
Des idées? Merci.
La réponse à votre question consiste à utiliser le &
au niveau du bit comme ceci:
SELECT * FROM UserTable WHERE Roles & 6 != 0
Le 6
peut être échangé contre n'importe quelle combinaison de votre champ binaire pour lequel vous souhaitez vérifier qu'un utilisateur possède un ou plusieurs de ces bits. Lorsque j'essaie de valider cela, je trouve généralement utile d'écrire cela en binaire. Votre table utilisateur ressemble à ceci:
1 2 4
------------------
Dave 0 1 1
Charlie 0 1 0
Susan 0 0 1
Nick 1 0 0
Votre test (6) est-ce
1 2 4
------------------
Test 0 1 1
Si nous examinons chaque personne en train de faire le bitwaise Et contre le test, nous obtenons ces:
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)
Ce qui précède doit démontrer que tous les enregistrements pour lesquels le résultat n'est pas nul ont un ou plusieurs des indicateurs demandés.
Edit: Voici le cas de test si vous voulez vérifier ceci
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
Utilisez l'opérateur Transact-SQL et AND au niveau du bit "&" et comparez le résultat à zéro. Mieux encore, au lieu de coder les rôles sous forme de bits d'une colonne entière, utilisez des colonnes booléennes, une pour chaque rôle. Dans ce cas, votre requête sera simplement adaptée aux concepteurs ET aux programmeurs. Si vous vous attendez à ce que les rôles changent beaucoup au cours de la vie de votre application, utilisez un tableau plusieurs-pour-plusieurs pour mapper l'association entre les utilisateurs et leurs rôles. les deux alternatives sont plus portables que de s'appuyer sur l'existence de l'opérateur bitwise-AND.
SELECT * FROM UserTable WHERE Roles & 6 > 0
exemple:
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
SELECT * FROM table WHERE masque1 & masque2> 0
Pour trouver tous les programmeurs, utilisez:
SELECT * FROM UserTable WHERE Roles & 2 = 2