SET BIT: примеры (SQL)

Работа с битами: руководство по функции SET_BIT в SQL Server
Раздел: Битовые функции, Битовые
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
--------
1110

Oracle: Предлагает пакет UTL_RAW для низкоуровневых операций, но для числовых типов обычно применяются побитовые функции: BITAND, BITOR и сдвиги через арифметические операции.

SELECT BITAND(6, ~POWER(2, 2)) FROM dual; -- Сброс бита 2
2

MySQL: Имеет стандартные побитовые операторы (&, |, ^, ~, <<, >>). Прямого аналога SET_BIT нет.

SQLite: Поддерживает побитовые операторы только для целых чисел. Аналога SET_BIT не существует.

Языки программирования (C-подобные синтаксисы): Часто используют комбинацию операторов, например, value |= (1 << bit_position) для установки бита. T-SQL SET_BIT инкапсулирует эту логику в одну функцию.

MS SQL SET_BIT function comments

En
SET BIT Sets a bit at a specified position to a value