我使用C#中的枚举的标志,一切都很好,但是想在以下情况下使用类似sql的东西:
我们希望返回列表中列出的用户列表或条件如下所示:
ConditionOne = 2 ConditionTwo = 4 ConditionThree = 8
等等…
User1: 6 (conditions 1 and 2) User2: 4 (condition 2) User3: 14 (conditions 1,2 and 3)
等等…
我们希望能够做一个查询,在这里我们会说所有使用条件1的用户,而且在这种情况下,即使他们有其他条件,它也会返回用户1和3.
任何洞察将不胜感激,只使用C#中的标志,而不直接在sql Server中使用.
解决方法
虽然James所建议的按位操作符会奏效,但在关系数据库中并不会很好,尤其是当您尝试扩展到数百万条记录时.原因是where子句中的函数是不可用的(它们阻止索引查找).
我会做的是创建一个包含所有可能的标志和条件组合的表,这将使索引在该条件下寻找.
填充FlagConditions.我用了一个(tinyint).如果你需要更多的标志,你应该能够扩展这种方法:
CREATE TABLE FlagConditions ( Flag TINYINT,Condition TINYINT,CONSTRAINT Flag_Condition PRIMARY KEY CLUSTERED (Condition,Flag) ); CREATE TABLE #Flags ( Flag TINYINT IDENTITY(0,1) PRIMARY KEY CLUSTERED,DummyColumn BIT NULL); GO INSERT #Flags ( DummyColumn ) SELECT NULL; GO 256 CREATE TABLE #Conditions(Condition TINYINT PRIMARY KEY CLUSTERED); INSERT #Conditions ( Condition ) VALUES (1),(2),(4),(8),(16),(32),(64),(128); INSERT FlagConditions ( Flag,Condition ) SELECT Flag,Flag & Condition FROM #Flags f CROSS JOIN #Conditions c WHERE Flag & Condition <> 0; DROP TABLE #Flags; DROP TABLE #Conditions;
现在,您可以随时使用FlagConditions表,以便有效地寻找枚举位置条件:
DECLARE @UserFlags TABLE (Username varchar(10),Flag tinyint); INSERT @UserFlags(Username,Flag) VALUES ('User1',6),('User2',4),('User3',14); DECLARE @Condition TINYINT = 2; SELECT u.* FROM @UserFlags u INNER JOIN FlagConditions fc ON u.Flag = fc.Flag WHERE fc.Condition = @Condition;
这返回:
Username Flag ---------- ---- User1 6 User3 14
你的DBA会感谢你去这个面向路线的路线.