Spec-Zone.ru › MySQL 5.7

12.12 Битовые функции и операторы

Таблица 12.17 Битовые функции и операторы

Таблица 12.17 Битовые функции и операторы
Имя Описание
& Битовое И
>> Сдвиг вправо
<< Сдвиг влево
^ Битовое XOR
BIT_COUNT() Возвращает количество установленных битов
| Битовое ИЛИ
~ Инвертирование всех битов

В следующем списке описаны доступные битовые функции и операторы:

  • |

    Битовое ИЛИ.

    Результат — целое беззнаковое 64-битное число.

    mysql> SELECT 29 | 15;
            -> 31
    
  • &

    Битовое И.

    Результат — целое беззнаковое 64-битное число.

    mysql> SELECT 29 & 15;
            -> 13
    
  • ^

    Битовое XOR.

    Результат — целое беззнаковое 64-битное число.

    mysql> SELECT 1 ^ 1;
            -> 0
    mysql> SELECT 1 ^ 0;
            -> 1
    mysql> SELECT 11 ^ 3;
            -> 8
    
  • <<

    Сдвигает целое число longlong (BIGINT) влево.

    Результат — целое беззнаковое 64-битное число. Значение усекается до 64 бит. В частности, если количество сдвигов больше или равно ширине 64-битного беззнакового числа, результат равен нулю.

    mysql> SELECT 1 << 2;
            -> 4
    
  • >>

    Сдвигает целое число longlong (BIGINT) вправо.

    Результат — целое беззнаковое 64-битное число. Значение усекается до 64 бит. В частности, если количество сдвигов больше или равно ширине 64-битного беззнакового числа, результат равен нулю.

    mysql> SELECT 4 >> 2;
            -> 1
    
  • ~

    Инвертирует все биты.

    Результат — целое беззнаковое 64-битное число.

    mysql> SELECT 5 & ~1;
            -> 4
    
  • BIT_COUNT(N)

    Возвращает количество установленных битов в аргументе N в виде целого беззнакового 64-битного числа или NULL, если аргумент равен NULL.

    mysql> SELECT BIT_COUNT(29), BIT_COUNT(b'101010');
            -> 4, 3
    

Битовые функции и операторы включают в себя BIT_COUNT(), BIT_AND(), BIT_OR(), BIT_XOR(), &, |, ^, ~, << и >>. (Функции BIT_AND(), BIT_OR() и BIT_XOR() — это агрегатные функции, описанные в разделе 12.19.1, «Описание агрегатных функций».) В настоящее время битовые функции и операторы требуют BIGINT (64-битное целое число) аргументы и возвращают BIGINT значения, поэтому они имеют максимальный диапазон 64 бит. Аргументы других типов преобразуются в BIGINT, и может произойти усечение.

Расширение для MySQL 8.0 изменяет это поведение преобразования в BIGINT: Битовые функции и операторы допускают аргументы типа двоичной строки (BINARY, VARBINARY и типы BLOB), что позволяет им принимать аргументы и генерировать возвращаемые значения, превышающие 64 бита. Следовательно, битовые операции над двоичными аргументами в MySQL 5.7 могут давать разные результаты в MySQL 8.0. Чтобы заранее предупредить об этом потенциальном изменении поведения, сервер с MySQL 5.7.11 генерирует предупреждения для битовых операций, для которых двоичные аргументы не преобразуются в целые числа в MySQL 8.0. Эти предупреждения дают возможность переписать затронутые операторы. Чтобы явно воспроизвести поведение MySQL 5.7 таким образом, что оно не изменится после обновления до 8.0, преобразуйте двоичные аргументы битовых операций в целые числа.

Пять типов проблемных выражений, на которые следует обратить внимание:

nonliteral_binary { & | ^ } binary
binary  { & | ^ } nonliteral_binary
nonliteral_binary { << >> } anything
~ nonliteral_binary
AGGR_BIT_FUNC(nonliteral_binary)

Эти выражения возвращают BIGINT в MySQL 5.7 и двоичную строку в 8.0.

Объяснение обозначений:

  • { op1 op2 ... }: Список операторов, которые применяются к данному типу выражения.

  • binary: Любой вид двоичного строкового аргумента, включая шестнадцатеричную литерал, битовую литерал или NULL литерал.

  • nonliteral_binary: Аргумент, являющийся значением двоичной строки, отличным от шестнадцатеричной литералы, битовой литералы или NULL литералы.

  • AGGR_BIT_FUNC: Агрегатная функция, принимающая аргументы битовых значений: BIT_AND(), BIT_OR(), BIT_XOR().

Сервер генерирует одно предупреждение для каждого проблемного выражения в операторе, а не для каждой обработанной строки. Предположим, что оператор, содержащий два проблемных выражения, выбирает три строки из таблицы. Количество предупреждений за выполнение оператора равно двум, а не шести. Следующий пример иллюстрирует это.

mysql> CREATE TABLE t(vbin1 VARBINARY(32), vbin2 VARBINARY(32));
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO t VALUES (3,1), (3,2), (3,3);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT HEX(vbin1 & vbin2) AS op1,
    -> HEX(vbin1 | vbin2) AS op2
    -> FROM t;
+------+------+
| op1  | op2  |
+------+------+
| 1    | 3    |
| 2    | 3    |
| 3    | 3    |
+------+------+
3 rows in set, 2 warnings (0.00 sec)

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1287
Message: Bitwise operations on BINARY will change behavior in a future
         version, check the 'Bit functions' section in the manual.
*************************** 2. row ***************************
  Level: Warning
   Code: 1287
Message: Bitwise operations on BINARY will change behavior in a future
         version, check the 'Bit functions' section in the manual.
2 rows in set (0.00 sec)

Чтобы избежать получения разного результата оператора после обновления до MySQL 8.0, перепишите его так, чтобы он не генерировал предупреждений для битовых операций. Для этого преобразуйте хотя бы один двоичный аргумент в BIGINT с помощью CAST(... AS UNSIGNED). Это делает неявное преобразование двоичной строки в целое число в MySQL 5.7 явным:

mysql> SELECT HEX(CAST(vbin1 AS UNSIGNED) & CAST(vbin2 AS UNSIGNED)) AS op1,
    -> HEX(CAST(vbin1 AS UNSIGNED) | CAST(vbin2 AS UNSIGNED)) AS op2
    -> FROM t;
+------+------+
| op1  | op2  |
+------+------+
| 1    | 3    |
| 2    | 3    |
| 3    | 3    |
+------+------+
3 rows in set (0.01 sec)

mysql> SHOW WARNINGS\G
Empty set (0.00 sec)

При переписанном операторе, как показано, MySQL 8.0 учитывает намерение обрабатывать двоичные аргументы как целые числа и возвращает тот же результат, что и в 5.7. Также воспроизведение оператора из MySQL 5.7 в 8.0 не приводит к разным результатам на разных серверах.

Затронутый оператор, который нельзя переписать, подвержен следующим потенциальным проблемам в отношении обновлений и репликации:

  • Оператор может вернуть другой результат после обновления до MySQL 8.0.

  • Репликация в MySQL 8.0 из более старых версий может завершиться неудачей для основанных на операторах и смешанных двоичных журналов. Это также верно для повторного воспроизведения более старых двоичных журналов на сервере 8.0 (например, с использованием mysqlbinlog). Чтобы этого избежать, переключитесь на основанную на строках двоичную запись на более старом исходном сервере.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/bit-functions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API