更新位掩码字段 (SQL Server) 中的一个特定位



我的SQL Server数据库中有一个包含8位的int列。如何在不影响其他位的情况下更新某些位?

例如,我有一个值

11010000 

我想将 bit1 和 bit2 设置为 1,所以它会变成

11010011

查看了按位运算符,但找不到正确的解决方案。

我的目标不仅是更新某些位,而且还要避免数据库锁定。

因此,当事务 1 更新特定记录中的 bit1 时,另一个事务 2 可以同时更新同一记录的同一字段中的 bit2。

这可能吗?还是使用 8 个单独的bit列是唯一的方法?

您要查找的是按位运算。 要始终打开正确的位,请使用按位 OR。因此,要打开位 1 和 2(总值 = 3(,请使用如下语句(假设 @value 中的值为 208 或 11010000 二进制(:

SET @value = @value | 3
-- or, the alternate form
SET @value |= 3

其他运算符是按位 AND (SET @value = @value & 3(、按位 NOT(SET @Value = @value ~ 3和按位 XOR (SET @value = @value ^ 3(。

也就是说,对于新程序员来说,拥有八个bit字段在逻辑上更容易。我不需要找到一些特别的东西来查看字段ShowCurrencySymbol是显示货币符号的标志,而不是找出字节中的第五位的作用。而且,由于字段在内部压缩,因此八个一位、不可为空的字段 = 一个字节的空间(添加 NULL 需要每位 2 位(。

最后,不能让两个交易记录同时更新同一行上的字段。 发生一个更新时,该行将被锁定,从而阻止处理另一个更新。如果你真的想要这样的东西,你将不得不使用一个更广泛的方法 - 一个单独的 BitValues 或 Flags 表,如下所示:

CREATE TABLE Flags (
RowID int not null,
FlagName varchar(16) Not Null,
BitValue bit not null,
CONSTRAINT PK_Flags PRIMARY KEY (RowID, FlagName)
);

然后,从此表中读取和写入与行分开的标志。

伪位集值是指您有一个整数或字符串,在选择或打印时,它看起来像一个位集。像这样:

DECLARE @bits varchar(8) = '1010'
SELECT Right(8, REPLICATIE('0', 8) + @bits
Value returned: 00001010

对于这种类型的位集,您需要记住,您不是在设置位,而是在表示位,并且您需要以相同的方式设置位的表示形式。 例如,下面的函数可用于在位字符串的字符串表示形式中设置位:

CREATE FUNCTION dbo.SetBitInString 
(
@Source char(8), 
@Position int,
@Action char(1) = 'S',
@Value bit = NULL
)
RETURNS Char(8)
AS
BEGIN
DECLARE @work Char(8) = '00000000'
SET @work = Right(@work + ISNULL(LTRIM(RTRIM(@Source)), ''), 8)
SET @Work = 
CASE @Action
WHEN 'S'-- Set
THEN Stuff(@Work, @Position, 1, '1')
WHEN 'R' -- Reset
THEN Stuff(@Work, @Position, 1, '0')
WHEN 'X' -- XOR value with position
THEN STUFF(@Work, @Position, 1, CAST(CAST(SubString(@Work, @Position, 1) as int) ^ ISNULL(@Value, 0) as CHAR(1)))
WHEN 'Q'
THEN '1'
---- add other options as needed - this is a quick example.
ELSE @Action
END
IF (@Action = @Work)
RAISERROR('Bad Action (%s) Submitted', 13, 1, @Action)
RETURN @Work
END

读取位是一个简单的子字符串。可以为每个位的含义定义常量(例如DECLARE @ShowTotalPrice = 4 -- The 4th bit is the Show Total Price flag(

如果要使用这种设置样式,这应该足以让您继续,其中显示的值是用 1 和 0 表示的位集。

最新更新