比较SQL中的两个位掩码以查看是否有任何位匹配

时间:2008-09-27 14:38:05

标签: sql sql-server tsql bitmask

有没有办法在Transact-SQL中比较两个位掩码以查看是否有任何位匹配?我有一个User表,其中包含用户所属角色的位掩码,我想在所提供的位掩码中选择所有任何角色的用户。因此,使用下面的数据,角色位6(设计师+程序员)应选择Dave,Charlie和Susan,但不能选择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

有什么想法吗?感谢。

6 个答案:

答案 0 :(得分:76)

您的问题的答案是使用像这样的按位&

SELECT * FROM UserTable WHERE Roles & 6 != 0

6可以替换您想要检查任何用户是否有一个或多个这些位的位域的任何组合。在尝试验证这一点时,我通常会发现以二进​​制形式写出这个有用的东西。您的用户表如下所示:

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

你的测试(6)就是这个

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

如果我们通过每个人进行比特和反对测试我们得到这些:

        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) 

以上内容应证明结果不为零的任何记录都有一个或多个请求的标志。

编辑:如果你想检查这个

,这是测试用例
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

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

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

答案 1 :(得分:6)

使用Transact-SQL bitwise AND operator“&”并将结果与​​零进行比较。更好的是,不要将角色编码为整数列的位,而是使用布尔列,每个角色一个。然后你的查询只是设计师和程序员友好。如果您希望角色在应用程序的生命周期内发生很大变化,那么请使用多对多表来映射用户与其角色之间的关联。两种替代方案都比依赖于按位AND运算符的存在更具可移植性。

答案 2 :(得分:5)

SELECT * FROM UserTable WHERE Roles & 6 > 0

答案 3 :(得分:2)

SELECT * FROM table WHERE mask1& mask2> 0

答案 4 :(得分:2)

示例:

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

答案 5 :(得分:0)

找到所有程序员使用:

SELECT * FROM UserTable WHERE Roles & 2 = 2