2008-09-27 31 views
41

有没有办法比较Transact-SQL中的两个位掩码来查看是否有任何位匹配?我有一个带有用户所有角色位掩码的用户表,并且我想选择所有在所提供的位掩码中具有任意角色的用户。因此,使用下面的数据,角色位掩码6(设计师+程序员)应该选择戴夫,查理和苏珊,但不是尼克。比较SQL中的两个位掩码以查看是否有任何位匹配

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

任何想法?谢谢。

回答

61

的回答你的问题是使用像这样的Bitwise &

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 

如果我们通过每个人做的bitwaise和反对的测试中,我们得到这些:

 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 
6

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

+0

&运算符适用于位掩码与一个角色相比较,但不用于比较位掩码和其他位掩码。我想我必须使用动态sql并将每个角色放入where子句中。 – Nick 2008-09-27 15:03:37

+1

@尼克 - 错 - 请参阅我的回答。 – Jamiec 2012-02-13 15:56:04

0

要查找所有程序员使用:

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

OP对于程序员或设计师来说很好看 – ScottE 2010-08-24 23:35:13

2

SELECT * FROM表WHERE掩码1 &掩码2> 0

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 
+0

这给出了错误的结果。尝试4 - 苏珊和戴夫都有4 - 但它只返回苏珊。 – Jamiec 2012-02-13 15:23:07

5
SELECT * FROM UserTable WHERE Roles & 6 > 0 
相关问题