SQL Server按位处理,如C#枚举标志
如何在SQL Server中使用诸如C#中的枚举上的标记处理SQL Server按位处理,如C#枚举标志,sql,sql-server,bitwise-operators,Sql,Sql Server,Bitwise Operators,如何在SQL Server中使用诸如C#中的枚举上的标记处理 例如,如何返回作为列表或类似条件一部分的用户列表: ConditionAlpha = 2 ConditionBeta = 4 ConditionGamma = 8 然后,会有一些用户遇到以下情况: User1: 6 (conditions Alpha and Beta) User2: 4 (condition Beta) User3: 14 (conditions Alpha, Beta and Gamma) 我们希望能够
例如,如何返回作为列表或类似条件一部分的用户列表:
ConditionAlpha = 2
ConditionBeta = 4
ConditionGamma = 8
然后,会有一些用户遇到以下情况:
User1: 6 (conditions Alpha and Beta)
User2: 4 (condition Beta)
User3: 14 (conditions Alpha, Beta and Gamma)
我们希望能够执行一个查询,其中我们说获取具有第一个条件Alpha的所有用户,在这种情况下,它将返回用户1和3,即使他们还有其他条件。检查SQL中是否设置了标志的按位运算符是
&
。WHERE
子句需要计算为BOOLEAN
表达式,如下所示:
create table #temp (id int, username varchar(20), flags int)
insert into #temp values
(1, 'User1', 6 /* (2 | 4) */),
(2, 'User2', 4),
(3, 'User3', 14 /* (2 | 4 | 8) */)
declare @ConditionOne int = 2
select *
from #temp
where flags & @ConditionOne <> 0
declare @ConditionTwo int = 4
select *
from #temp
where flags & @ConditionTwo <> 0
declare @ConditionThree int = 8
select *
from #temp
where flags & @ConditionThree <> 0
drop table #temp
虽然James建议的按位运算符可以工作,但在关系数据库中,它的性能不是很好,特别是当您试图扩展到数百万条记录时。原因是where子句中的函数不可用(它们阻止索引查找) 我要做的是创建一个表,其中包含所有可能的标志和条件组合,这将启用对条件的索引搜索 填充条件。我用了一个(罐头)。如果您需要更多标志,您应该能够扩展此方法:
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;
这将返回:
Username Flag
---------- ----
User1 6
User3 14
您的DBA将感谢您选择这种面向集合的路线。我遇到了几乎相同的问题,可以提出这样的解决方案:
SELECT t.value
, ISNULL(t.C1 + ', ', '') + ISNULL(t.C2, '') + ISNULL(', ' + t.C3, '') AS [type]
FROM
(
SELECT value,
CASE WHEN (type & 2) <> 0 THEN 'Type1' END AS C1,
CASE WHEN (type & 4) <> 0 THEN 'Type2' END AS C2,
CASE WHEN (type & 8) <> 0 THEN 'Type3' END AS C3
FROM db.Agent
) t
C#Enum:
CopEntry=1将此信息存储在多对多表中更像“SQL”。因此,您需要将行(1,1)、(1,2)、(2,2)、(3,1)、(3,2)、(3,3)
存储在单独的表中。这将有助于更自然的查询,并提供索引机会。我不明白当这个答案包含的SQL实际上甚至没有解析(“GO256”)时,它怎么会有20次投票。即使在删除256之后,它也不会执行答案所说的操作。@IanKemp这将在SSMS或sqmcmd中工作。GO不是一个T-SQL语句,而是一个批处理分隔符。它被诸如SSMS之类的sql工具识别。它的语法是GO[count]
,其中count是运行前一批的次数。因此,在本例中,它将运行insert 256次。docselegant但是如果你需要在两个或更多的条件下进行过滤呢?你会为每个条件做额外的连接吗?
Username Flag
---------- ----
User1 6
User3 14
SELECT t.value
, ISNULL(t.C1 + ', ', '') + ISNULL(t.C2, '') + ISNULL(', ' + t.C3, '') AS [type]
FROM
(
SELECT value,
CASE WHEN (type & 2) <> 0 THEN 'Type1' END AS C1,
CASE WHEN (type & 4) <> 0 THEN 'Type2' END AS C2,
CASE WHEN (type & 8) <> 0 THEN 'Type3' END AS C3
FROM db.Agent
) t
value type
---------- ------------------------------------
14 Type1, Type2, Type3
12 Type2, Type3
14 Type1, Type2, Type3