将多个位值存储在单个表列中

时间:2012-03-10 02:41:54

标签: sql sql-server sql-server-2008 tsql

我需要在数据库中存储某种类型的星期日程安排,我可以在一天或一天​​中的多天安排记录(比如它代表一项任务)。我需要将它存储在一列中,以便于保存和检索。然后我每天选择日程安排与当前星期几匹配的记录,例如:给我所有记录,并安排第7周的日程安排。

我想到的是一系列7位,每一位代表星期几,其中0表示不计划,1表示计划。例如:对于日常任务的情况为“1111111”,对于仅在一周的第一天运行的任务为“1000000”。

为了清楚起见,记录可以安排在任何天的组合中,我不知道,因此检索中的唯一输入是搜索的工作日。

我在这里有两个问题:

  1. 在SQL Server 2008中存储此类数据的最佳方法是什么?以某种方式允许根据当周的当前日期轻松查询。

  2. 上述方法有哪些更好的替代方案。我需要高效且易于实施的解决方案。

4 个答案:

答案 0 :(得分:7)

您可以将其存储为位域,然后使用布尔逻辑运算符来检索值

例如:

CREATE TABLE [dbo].[testBF](
    [field1] [varchar](max) NOT NULL,
    [field2] [varchar](max) NOT NULL,
    [bitfield] [int] NOT NULL CONSTRAINT [DF_testBF_bitfield]  DEFAULT ((0))
) ON [PRIMARY]

然后选择:

SELECT field1, field2,
       CASE WHEN (bitfield & 1) = 1 THEN 'monday ' ELSE '' END + 
       CASE WHEN (bitfield & 2) = 2 THEN 'tuesday ' ELSE '' END +
       CASE WHEN (bitfield & 4) = 4 THEN 'wednesday ' ELSE '' END +
       CASE WHEN (bitfield & 8) = 8 THEN 'thursday ' ELSE '' END +
       CASE WHEN (bitfield & 16) = 16 THEN 'friday' ELSE '' END as [days of week]
FROM testBF

查找包含星期二旗帜的所有日子(星期二是第2位或2 ^ 1或2)

SELECT * 
FROM aTable
WHERE (bitfield & 2) = 2

SELECT * 
FROM aTable
WHERE (bitfield & 2) != 0

注意,第二种情况下的模板适用于任何位 - 即星期五(第5位或2 ^ 4或16位)

SELECT * 
FROM aTable
WHERE (bitfield & 16) != 0

最后一般情况......传递一个数字(星期一为1)你得到

SELECT * 
FROM aTable
WHERE (bitfield & POWER(2,@inNumOfWeekday-1)) != 0

这对我来说似乎很多工作,当你可以将其保存为5(或7位字段)时,这就是你可以做到的。

有关更多示例,请查看我为另一个问题撰写的要点:

https://gist.github.com/1846338

和答案:

https://stackoverflow.com/a/9302106/215752

答案 1 :(得分:1)

你在谈论一个“位掩码”。这些是方便的设备,因为您可以对它们应用二进制数学来轻松检查值,但它们确实需要一些设置。为了进一步扩展它会看起来像这样。

-- You will want to work with constants
DECLARE @Mon INT, @Tue INT, @Wed INT, @Thu INT, @Fri INT, @Sat INT, @Sun INT

SET @Mon = POWER(2,0) -- 1
SET @Tue = POWER(2,1) -- 2
SET @Wed = POWER(2,2) -- 4
SET @Thu = POWER(2,3) -- 8
SET @Fri = POWER(2,4) -- 16
SET @Sat = POWER(2,5) -- 32
SET @Sun = POWER(2,6) -- 64

-- Set Monday and Wednesday
UPDATE T SET Schedule = @Mon | @Wed

-- Find all tasks scheduled on Tuesday
SELECT * FROM T WHERE Schedule & @Tue = @Tue

-- Find all tasks scheduled on Tuesday and Saturday
SELECT * FROM T WHERE Schedule & @Tue | @Sat = @Tue | @Sat

答案 2 :(得分:0)

我不确定你的简单查询是什么意思。一旦你将它包装在一个函数中就很容易了。轻松即席查询的选项可能是具有易于读取的字符串字段,并使用一些字符串操作过程来完成它。例如:

UPDATE T SET Schedule = 'M|W|H'

SELECT * FROM T WHERE CHARINDEX(Schedule, 'M') > -1

答案 3 :(得分:0)

从标题开始,我被带到这里的情况是表中已有位字段,并且需要转换为单个整数字段。

在下面的“星期几”示例中,假设有7个要转换为名为Schedule的(位掩码)整数字段的单个位字段:

while(true)