Frage

Gibt es eine Möglichkeit zwei Bitmasken in Transact-SQL zu vergleichen, um zu sehen, ob eines der Bits übereinstimmen? Ich habe für alle Rollen einer Benutzertabelle mit einem bitmask bekam der Benutzer gehört, und ich möchte alle Benutzer auswählen, haben alle der Rollen in der mitgelieferten Bitmaske. So unter Verwendung der Daten, ein Rollen bitmask von 6 (Designern + Programmierer) soll Dave, Charlie und Susan wählen, aber nicht 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

Irgendwelche Ideen? Danke.

War es hilfreich?

Lösung

Die Antwort auf Ihre Frage ist die bitweise & wie folgt zu verwenden:

SELECT * FROM UserTable WHERE Roles & 6 != 0

Die 6 kann für jede mögliche Kombination Ihrer bitfield ausgetauscht werden, wenn Sie überprüfen möchten, dass jeder Benutzer eine oder mehrere dieser Bits hat. Beim Versuch, diese zu validieren finde ich in der Regel hilfreich es diese Langschrift binär zu schreiben. Ihr Benutzertabelle sieht wie folgt aus:

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

Ihr Test (6) ist dies

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

Wenn wir durch jede Person gehen, um die bitwaise tun und gegen den Test, den wir bekommen 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 oben gezeigte soll zeigen, dass alle Datensätze, bei denen das Ergebnis nicht Null ein oder mehrere der angeforderten Flags hat.

Edit: Hier ist der Testfall sollten Sie dies überprüfen

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

Andere Tipps

Verwenden Sie den Transact-SQL bitweise AND-Operator "&" und vergleichen Sie das Ergebnis auf Null. Noch besser ist, statt die Codierung der Rollen als Bits einer Integer-Spalte, verwenden boolean Spalten, eine für jede Rolle. Dann würde Ihre Frage einfach Designer und Programmierer freundlich sein. Wenn Sie die Rollen erwarten viel über die gesamte Lebensdauer Ihrer Anwendung zu ändern, verwenden Sie dann eine many-to-many-Tabelle, die die Zuordnung zwischen Benutzern und ihren Rollen abzubilden. Beide Alternativen sind mehr tragbar als auf die Existenz des bitweise AND-Operator angewiesen zu sein.

SELECT * FROM UserTable WHERE Roles & 6 > 0

SELECT * FROM Tabelle WHERE mask1 & mask2> 0

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

Für alle Programmierer verwenden:

SELECT * FROM UserTable WHERE Roles & 2 = 2
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top