2008-09-27 33 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 
相關問題