位函数和运算符包括
BIT_COUNT()
,
BIT_AND()
,
BIT_OR()
,
BIT_XOR()
,
&
,
|
,
^
,
~
,
<<
和
>>
。(BIT_AND()
、
BIT_OR()
和
BIT_XOR()
函数是第 12.20.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 中未转换为整数的位操作生成警告。这些警告提供了重写受影响语句的机会。要以升级到 8.0 后不会更改的方式显式生成 MySQL 5.7 行为,请转换位操作二进制参数以将它们转换为整数。
需要注意的五种有问题的表达类型是:
nonliteral_binary { & | ^ } binary
binary { & | ^ } nonliteral_binary
nonliteral_binary { << >> } anything
~ nonliteral_binary
AGGR_BIT_FUNC(nonliteral_binary)
这些表达式BIGINT
在 MySQL 5.7 中返回,在 8.0 中返回二进制字符串。
符号说明:
服务器为语句中的每个有问题的表达式生成一个警告,而不是为处理的每一行生成一个警告。假设包含两个有问题的表达式的语句从表中选择三行。每个语句执行的警告数是两个,而不是六个。下面的例子说明了这一点。
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
with
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)。为避免这种情况,请切换到旧源服务器上的基于行的二进制日志记录。
以下列表描述了可用的位函数和运算符:
按位或。
结果是一个无符号的 64 位整数。
mysql> SELECT 29 | 15; -> 31
按位与。
结果是一个无符号的 64 位整数。
mysql> SELECT 29 & 15; -> 13
按位异或。
结果是一个无符号的 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
返回在参数中设置
N
为无符号 64 位整数的位数,或者NULL
如果参数是NULL
.mysql> SELECT BIT_COUNT(29), BIT_COUNT(b'101010'); -> 4, 3