Question

Existe-t-il un moyen de comparer deux masques de bits dans Transact-SQL pour déterminer 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 un 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.

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

Des idées? Merci.

Était-ce utile?

La solution

La réponse à votre question est d'utiliser le & amp; de Bitwise comme ceci:

SELECT * FROM UserTable WHERE Roles & 6 != 0

Le 6 peut être échangé contre toute combinaison de votre champ binaire pour lequel vous souhaitez vérifier que tout 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, nous obtenons ces tests:

        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 dont le résultat est différent de zéro possèdent un ou plusieurs des indicateurs demandés.

Éditer: voici le scénario de test si vous souhaitez 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

Autres conseils

Utilisez le opérateur AND au niveau du bit AND au format Transact-SQL. ; " 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. Ensuite, votre requête sera simplement concepteur ET programmeur convivial Si vous vous attendez à ce que les rôles changent beaucoup au cours de la durée de 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 compter sur l’existence de l’opérateur bitwise-AND.

SELECT * FROM UserTable WHERE Roles & 6 > 0

SELECT * FROM table WHERE masque1 & amp; masque2 > 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

Pour trouver tous les programmeurs, utilisez:

SELECT * FROM UserTable WHERE Roles & 2 = 2
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top