55

有没有办法比较 Transact-SQL 中的两个位掩码以查看是否有任何位匹配?我有一个用户表,其中包含用户所属的所有角色的位掩码,我想选择在提供的位掩码中具有任何角色的所有用户。所以使用下面的数据,角色位掩码 6(设计师+程序员)应该选择 Dave、Charlie 和 Susan,而不是 Nick。

用户表
----------
ID 用户名角色
1 戴夫 6
2查理2
3 苏珊 4
4 尼克 1

角色表
------------
身份角色
1 名管理员
2 程序员
4 设计师

有任何想法吗?谢谢。

4

6 回答 6

93

您的问题的答案是&像这样使用 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
于 2012-02-13T15:36:36.120 回答
6

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

于 2008-09-27T14:41:22.613 回答
5
SELECT * FROM UserTable WHERE Roles & 6 > 0
于 2012-02-13T14:59:04.043 回答
2

SELECT * FROM table WHERE mask1 & mask2 > 0

于 2010-08-24T22:28:13.943 回答
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
于 2010-08-24T23:21:08.533 回答
0

要查找所有程序员,请使用:

SELECT * FROM UserTable WHERE Roles & 2 = 2
于 2008-09-27T16:08:34.247 回答