Установка 32-го и 64-го битов сложная задача.
32-битный Решение:
Я получил его для работы с 32-битными полями.Хитрость заключается в приведении возвращаемого значения функции POWER к двоичному (4) перед преобразованием его в int.Если вы попытаетесь привести непосредственно к int, без предварительного преобразования к двоичному (4), вы получите исключение арифметического переполнения при работе с 32-м битом (индекс 31).Кроме того, вы должны убедиться, что переданное в POWER выражение имеет достаточно большой тип (например, bigint) для хранения максимального возвращаемого значения (2 ^ 31), иначе функция POWER вызовет исключение арифметического переполнения.
CREATE FUNCTION [dbo].[SetIntBit]
(
@bitfieldvalue int,
@bitindex int, --(0 to 31)
@bit bit --(0 or 1)
)
RETURNS int
AS
BEGIN
DECLARE @bitmask int = CAST(CAST(POWER(CAST(2 as bigint),@bitindex) as binary(4)) as int);
RETURN
CASE
WHEN @bit = 1 THEN (@bitfieldvalue | @bitmask)
WHEN @bit = 0 THEN (@bitfieldvalue & ~@bitmask)
ELSE @bitfieldvalue --NO CHANGE
END
END
64-битная Проблема:
Я собирался использовать аналогичный подход для 64-битных полей, однако я обнаружил, что функция POWER возвращает неточные значения, несмотря на использование десятичного числа (38) тип для выражения / возвращаемого значения.Например: «select POWER (CAST (2 as decimal (38)), 64)» возвращает 18446744073709552000 (точны только первые 16 цифр), а не правильное значение 18446744073709551616. И даже если бы я поднял только 2 до63-й степени, этот результат все еще неточен.
В документации функции POWER указано, что «внутреннее преобразование в число с плавающей запятой может привести к потере точности, если используются денежные или числовые типы данных».(обратите внимание, что числовой тип функционально эквивалентен десятичному типу).
Я думаю, что единственный способ правильно обработать 64-битные поля - это работать с их 32-битными половинками, но это требует дополнительной проверки @Свойство bitindex, чтобы увидеть, с какой половиной мне нужно работать.Существуют ли какие-либо встроенные функции или более эффективные способы явной установки этих конечных битов в 32-битных и 64-битных битовых полях в TSQL?