it-swarm.com.de

Beim Vergleich zweier Bitmasken in SQL, ob eines der Bits übereinstimmt

Gibt es eine Möglichkeit, zwei Bitmasken in Transact-SQL zu vergleichen, um zu sehen, ob eines der Bits übereinstimmt? Ich habe eine Benutzertabelle mit einer Bitmaske für alle Rollen, denen der Benutzer angehört, und ich möchte alle Benutzer auswählen, die beliebige der Rollen in der mitgelieferten Bitmaske haben. Unter Verwendung der folgenden Daten sollte eine Rollen-Bitmaske von 6 (Designer + Programmierer) Dave, Charlie und Susan auswählen, Nick jedoch nicht.

Benutzertabelle
----------
ID Benutzername Rollen 
 1 Dave 6 
 2 Charlie 2 
 3 Susan 4 
 4 Nick 1 

Roles Table
-----------
ID Rolle 
 1 Admin 
 2 Programmierer 
 4 Designer

Irgendwelche Ideen? Vielen Dank.

44
Nick

Die Antwort auf Ihre Frage ist die Verwendung des bitweisen & wie folgt:

SELECT * FROM UserTable WHERE Roles & 6 != 0

Der 6 kann gegen eine beliebige Kombination Ihres Bitfelds ausgetauscht werden, in dem Sie überprüfen möchten, ob ein Benutzer eines oder mehrere dieser Bits hat. Wenn ich versuche, dies zu bestätigen, finde ich es normalerweise hilfreich, diese Langschrift in Binärform zu schreiben. Ihre Benutzertabelle sieht so aus:

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

Dein Test (6) ist dieser

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

Wenn wir jede Person, die das Bitwaise durchführt, durchgehen, und gegen den Test bekommen wir diese:

        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) 

Das Obige sollte zeigen, dass alle Datensätze, bei denen das Ergebnis nicht Null ist, eine oder mehrere der angeforderten Flags aufweisen.

Bearbeiten: Hier ist der Testfall, falls Sie dies überprüfen möchten

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

oder 

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

oder

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

Verwenden Sie den Transact-SQL bitweisen AND-Operator "&" und vergleichen Sie das Ergebnis mit Null. Besser noch, anstatt die Rollen als Bits einer ganzzahligen Spalte zu codieren, verwenden Sie boolesche Spalten (eine für jede Rolle). Dann wäre Ihre Frage einfach Designer UND Programmiererfreundlich. Wenn Sie davon ausgehen, dass sich die Rollen während der gesamten Lebensdauer Ihrer Anwendung stark ändern werden, verwenden Sie eine Many-to-Many-Tabelle, um die Zuordnung zwischen Benutzern und ihren Rollen abzubilden. Beide Alternativen sind tragbarer als das Vorhandensein des bitweisen AND-Operators.

6
SELECT * FROM UserTable WHERE Roles & 6 > 0
5
Ben

beispiel:

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
2
ScottE

SELECT * FROM Tabelle WHERE Maske1 & Maske2> 0

2
vsevik

Um alle Programmierer zu finden, verwenden Sie:

SELECT * FROM UserTable WHERE Roles & 2 = 2
0
Sklivvz