SET BIT: примеры (SQL)
SET_BIT(expression bit string, position integer, new_value integer): bit stringОписание функции SET_BIT
Функция SET_BIT появилась в Microsoft SQL Server, начиная с версии 2022. Она предназначена для манипуляции отдельными битами в числовых значениях. Эта функция выполняет побитовые операции установки, сброса или переключения конкретного бита в целочисленном выражении.
Функция используется в сценариях, где данные хранятся в компактном виде с использованием битовых флагов, масок или статусов. Типичные примеры: управление правами доступа, хранение множественных булевых состояний в одном поле, обработка аппаратных регистров или специфических протоколов данных.
Аргументы функции
SET_BIT ( expression, bit_expression, bit_value )- expression: Исходное числовое выражение (типы
tinyint,smallint,int,bigint,bit,decimalилиnumericс масштабом 0). Это значение, бит в котором необходимо изменить. - bit_expression: Целочисленное выражение, указывающее позицию (индекс) изменяемого бита. Отсчет начинается с 0 для младшего (самого правого) бита. Допустимый диапазон зависит от типа первого аргумента.
- bit_value: Целочисленное выражение, определяющее операцию над битом. Допустимы три значения:
0— установить бит в 0 (сбросить).1— установить бит в 1 (установить).2— переключить (инвертировать) текущее значение бита.
Возвращаемое значение
Функция возвращает значение того же типа, что и входной аргумент expression. Если bit_expression указывает на позицию за пределами битового представления числа, функция возвращает исходное значение без изменений.
Короткие примеры использования
Пример 1: Установка бита в позицию 1.
SELECT SET_BIT(0, 1, 1) AS Result;Result
-------
2Пример 2: Сброс бита в позиции 2 у числа 6 (двоичное 110).
SELECT SET_BIT(6, 2, 0) AS Result;Result
-------
2Пример 3: Переключение (инвертирование) бита в позиции 0 у числа 5 (101).
SELECT SET_BIT(5, 0, 2) AS Result;Result
-------
4Пример 4: Использование с разными типами данных (bigint).
SELECT SET_BIT(CAST(255 AS bigint), 8, 1) AS Result;Result
-------
511Пример 5: Позиция бита за границами типа (для tinyint).
SELECT SET_BIT(CAST(10 AS tinyint), 10, 1) AS Result;Result
-------
10Похожие функции в MS SQL
До появления SET_BIT побитовые операции выполнялись с помощью стандартных операторов.
- Побитовые операторы (&, |, ^, ~): Базовые операции И, ИЛИ, исключающее ИЛИ и НЕ. Они работают на уровне всех битов числа одновременно, а не с отдельным битом. Для работы с конкретным битом требовалось комбинировать операторы с операцией сдвига.
- Операторы сдвига (<<, >>): Сдвигают биты числа влево или вправо. Часто используются вместе с побитовыми операторами для создания масок.
SET_BIT предпочтительнее, когда логика привязана к конкретному индексу бита (например, бит №3 означает «активен»). Это делает код более читаемым и выразительным по сравнению с ручным созданием масок. Классические операторы остаются в силе для сложных составных масок или операций сразу над группой битов.
Типичные ошибки
Ошибка 1: Передача недопустимого значения для bit_value (кроме 0, 1, 2).
SELECT SET_BIT(10, 2, 3);Msg 8116, Level 16, State 1, Line 1
Argument error: '3' is not a valid value for argument 3 of bitwise function 'set_bit'. Valid values are 0, 1, and 2.Ошибка 2: Отрицательная позиция бита.
SELECT SET_BIT(10, -1, 1);Msg 8116, Level 16, State 1, Line 1
Argument error: '-1' is not a valid value for argument 2 of bitwise function 'set_bit'.Ошибка 3: Использование типа с плавающей точкой или числового типа с масштабом больше 0 для первого аргумента.
SELECT SET_BIT(10.5, 2, 1);Msg 8115, Level 16, State 2, Line 1
Arithmetic overflow error converting numeric to data type numeric.Важно помнить, что функция не генерирует ошибку при указании позиции бита за пределами размера типа, а просто возвращает исходное число, что иногда может привести к логической ошибке в вычислениях.
История изменений
Функция SET_BIT была впервые представлена в Microsoft SQL Server 2022. В более ранних версиях (SQL Server 2019 и старше) эта функция недоступна. Её появление является частью расширения поддержки побитовых операций в T-SQL. В текущей реализации (SQL Server 2022) с момента релиза существенных изменений в её работе или синтаксисе не вносилось.
Расширенные примеры применения
Пример 1: Управление набором флагов (права доступа).
DECLARE @permissions tinyint = 0; -- Нет прав
-- Устанавливаем право на чтение (бит 0) и запись (бит 1)
SET @permissions = SET_BIT(@permissions, 0, 1);
SET @permissions = SET_BIT(@permissions, 1, 1);
SELECT @permissions AS PermissionsWithWrite;
-- Снимаем право на запись
SET @permissions = SET_BIT(@permissions, 1, 0);
SELECT @permissions AS PermissionsReadOnly;PermissionsWithWrite
--------------------
3
PermissionsReadOnly
--------------------
1Пример 2: Обработка статусов в цикле или наборе строк.
WITH Bits AS (
SELECT value, bit_pos
FROM (VALUES (5), (9), (12)) AS T(value)
CROSS JOIN (VALUES (0), (1), (2), (3)) AS P(bit_pos)
)
SELECT value, bit_pos,
SET_BIT(value, bit_pos, 2) AS ToggledValue
FROM Bits
ORDER BY value, bit_pos;value | bit_pos | ToggledValue
------|---------|-------------
5 | 0 | 4
5 | 1 | 7
5 | 2 | 1
5 | 3 | 13
9 | 0 | 8
9 | 1 | 11
9 | 2 | 13
9 | 3 | 1
12 | 0 | 13
12 | 1 | 14
12 | 2 | 8
12 | 3 | 4Пример 3: Построение битовой маски динамически.
DECLARE @mask int = 0;
DECLARE @bitsToSet TABLE (pos int);
INSERT INTO @bitsToSet VALUES (0), (3), (5);
SELECT @mask = SET_BIT(@mask, pos, 1)
FROM @bitsToSet;
SELECT @mask AS DynamicMask,
CAST(@mask AS varbinary(4)) AS MaskHex;DynamicMask | MaskHex
----------- | -------
41 | 0x00000029Пример 4: Эмуляция работы с отдельными байтами большого числа.
-- Установка 3-го бита в старшем байте числа типа int
DECLARE @value int = 0;
-- Старший байт (байт №3, считая с 0) - биты с 24 по 31.
-- Установим бит №25 (внутри байта это позиция 1).
SET @value = SET_BIT(@value, 25, 1);
SELECT @value AS Result, CAST(@value AS binary(4)) AS BinaryView;Result | BinaryView
-------- | ----------
33554432 | 0x02000000Аналоги в других СУБД и языках
PostgreSQL: Использует операторы |, &, ^ и функцию set_bit для работы с битовыми строками (bit strings), которая имеет другую сигнатуру: set_bit(bit_string, index, new_value).
SELECT set_bit(B'1010', 2, 1);set_bit
--------
1110Oracle: Предлагает пакет UTL_RAW для низкоуровневых операций, но для числовых типов обычно применяются побитовые функции: BITAND, BITOR и сдвиги через арифметические операции.
SELECT BITAND(6, ~POWER(2, 2)) FROM dual; -- Сброс бита 22MySQL: Имеет стандартные побитовые операторы (&, |, ^, ~, <<, >>). Прямого аналога SET_BIT нет.
SQLite: Поддерживает побитовые операторы только для целых чисел. Аналога SET_BIT не существует.
Языки программирования (C-подобные синтаксисы): Часто используют комбинацию операторов, например, value |= (1 << bit_position) для установки бита. T-SQL SET_BIT инкапсулирует эту логику в одну функцию.