位函数和运算符组成BIT_COUNT ()
那bit_and()
那bit_or()
那BIT_XOR ()
那&
那|
那^
那〜
那<<
,>>
。(bit_and()
那bit_or()
,BIT_XOR ()
汇总函数描述于第12.20.1节“汇总函数描述”。)在MySQL 8.0之前,需要位函数和操作符长整型数字
(64位整数)参数并返回长整型数字
值,因此它们的最大范围是64位。非长整型数字
争论被转换为长整型数字
在执行操作之前,可能发生截断。
在MySQL 8.0中,位函数和运算符允许二进制字符串类型参数(二进制
那varbinary.
,而且团
类型)并返回类似类型的值,这使它们能够采用参数并产生大于64位的返回值。非边区字符串参数转换为长整型数字
并如前所述处理。
行为变化的含义是二进制字符串参数的位操作可能比5.7中的MySQL 8.0中的不同结果产生不同的结果。有关如何在MySQL 5.7中准备的信息,以获取MySQL 5.7和8.0之间的潜在不兼容,请参阅位函数和操作符,在MySQL 5.7参考手册。
mysql 8.0之前的位操作只处理无符号64位整数参数和结果值(即unsigned长整型数字
价值观)。转换其他类型的论据长整型数字
是必要的。例子:
该语句处理的是作为无符号64位整数处理的数字字面值:
mysql> SELECT 127 | 128, 128 << 2, BIT_COUNT(15);+-----------+----------+---------------+ | 127 | 128 | 128 | < < 2 BIT_COUNT (15 ) | +-----------+----------+---------------+ | 255 | 512 | 4 | +-----------+----------+---------------+
该语句对字符串参数(
“127”
至127
等等)在执行与第一个语句相同的操作之前并产生相同的结果:mysql >选择“127”|“128”,“128”< < 2,BIT_COUNT (15);+---------------+------------+-----------------+ | ' 127 | 128 | 128年< < 2 | BIT_COUNT (' 15 ') | +---------------+------------+-----------------+ | 255 | 512 | 4 | +---------------+------------+-----------------+
此语句使用对位操作参数的十六进制文字。默认情况下,MySQL将十六进制文字视为二进制字符串,但在数字上下文中将它们评估为数字(参见第9.1.4节,“十六进制字面值”)。在MySQL 8.0之前,数字上下文包含位操作。例子:
mysql >选择X ' 7 f”|“80”X“80”< < 2,BIT_COUNT (X ' 0 f ');+---------------+------------+------------------+ | 7 X ' f ' | X ' 80 ' | X‘80’< < 2 | BIT_COUNT f (X ' 0 ') | +---------------+------------+------------------+ | 255 | 512 | 4 | +---------------+------------+------------------+
位操作中的位值字面量的处理类似于十六进制字面量(即数字)。
MySQL 8.0扩展了位操作,直接处理二进制字符串参数(不进行转换)并产生二进制字符串结果。(与前面一样,非整数或二进制字符串的参数仍然会被转换为整数。)这个扩展增强了以下方式的位操作:
对大于64位的值进行位操作成为可能。
对更自然地表示为二进制字符串而不是整数的值执行位操作更容易。
例如,考虑UUID值和IPv6地址,其具有这样的人类可读文本格式:
UUID: 6ccd780c-baba-1026-9564-5b8c656024db IPv6: fe80::219:d1ff:fe91:1a72
在这些格式中操作文本字符串是很麻烦的。另一种方法是将它们转换为不带分隔符的固定长度的二进制字符串。UUID_TO_BIN()
和INET6_ATON()
每个都产生数据类型的值二进制(16)
,二进制字符串16字节(128位)长。以下语句说明了这一点(十六进制()
用于生成可显示值):
mysql>选择hex(UUID_TO_BIN('6CCD780C-BABA-1026-9564-5B8C656024DB')));+ --------------------------------------------------- + |十六进制(UUID_TO_BIN('6CCD780C-BABA-1026-9564-5B8C656024DB'))|+ --------------------------------------------------- + |6CCD780CBABA102695645B8C656024DB |+ --------------------------------------------------- + mysql>选择hex(INET6_ATON('FE80 :: 219:D1FF:FE91:1A72'));+ ---------------------------------------- + |十六进制(INET6_ATON('FE80 :: 219:D1FF:FE91:1A72'))|+ ---------------------------------------- + | FE800000000000000219D1FFFE911A72 | +---------------------------------------------+
这些二进制值很容易通过位操作进行操作,例如从UUID值中提取时间戳,或提取IPv6地址的网络和主机部分。(有关示例,请参见后面的讨论。)
作为二进制字符串的参数包括列值、例程参数、局部变量和具有二进制字符串类型的用户定义变量:二进制
那varbinary.
,或其中之一团
类型。
十六进制文字和位文字怎么样?回想一下,在MySQL中默认为二进制字符串,但数字上下文中的数字。如何在MySQL 8.0中为位操作处理?MySQL是否继续在数字上下文中评估它们,如MySQL 8.0之前的那样?或Do位操作将它们评估为二进制字符串,现在可以处理二进制字符串“本机“没有转换?
答:通常使用十六进制字面值或位字面值来指定参数来表示数字,所以MySQL继续在数字上下文中计算位操作,当所有的位参数都是十六进制或位字面值时,为了向后兼容性。如果您要求以二进制字符串的形式求值,这很容易完成:使用_binary
至少一个文字的介绍者。
这些位操作将十六进制文字和位文字评估为整数:
mysql>选择x'40'|X'01',B'11110001'&B'01001111';+ -------------- + ------------------------ + |X'40'|X'01'|B'11110001'&B'01001111'|+ -------------- + ------------------------ + |65 |65 |+ -------------- + ------------------------- +
这些位操作会评估十六进制文字和位文字作为二进制字符串,由于
_binary
介绍者:mysql>选择_binary x'40'|X'01',B'11110001'&_binary b'01001111';+ -------------------------------------------------- + |_binary x'40'|X'01'|b'11110001'&_binary b'01001111'|+ -------------------------------------------------- + |a |a |+ -------------------------------------------------- +
虽然两个语句中的位操作产生了数值65的结果,但是第二语句在二进制字符串上下文中运行,其中65是ASCII一种
。
在数字评估上下文中,十六进制文字和比特文字参数的允许值最多是64位,结果是结果。相比之下,在二进制字符串评估上下文中,允许的参数(和结果)可能超过64位:
mysql> SELECT _binary X' 404040404040404040 ' | X'0102030405060708';+---------------------------------------------------+ | _ 二进制X ' 4040404040404040 ' | X ' 0102030405060708 ' | +---------------------------------------------------+ | ABCDEFGH | +---------------------------------------------------+
有几种方法可以在比特操作中引用十六进制文字或位文字来导致二进制字符串评估:
_binary文字二进制文字演员(文字作为二进制)
制作十六进制文字或位文字的二进制字符串评估的另一种方法是将它们分配给用户定义的变量,这导致具有二进制字符串类型的变量:
mysql> SET @v1 = X'40', @v2 = X'01', @v3 = b'11110001', @v4 = b'01001111';mysql> SELECT @v1 | @v2, @v3 & @v4;+-----------+-----------+ | @ v1 | @v2 | @v3 & @v4 | +-----------+-----------+ | 一个| | +-----------+-----------+
在二进制字符串上下文中,按位操作参数必须具有相同的长度或er_invalid_bitwise_operands_size.
发生错误:
mysql> SELECT _binary X'40' | X'0001';ERROR 3513 (HY000):二进制操作数的位操作符必须是相等的长度
为了满足等长要求,用前导零填充较短的值,或者,如果较长的值以前导零开头,并且可以接受较短的结果值,去掉它们:
mysql> SELECT _binary X'0040' | X'0001';+---------------------------+ | _ 二进制X ' 0040 ' | X ' 0001 ' | +---------------------------+ | 一个 | +---------------------------+ mysql >选择_binary X 40 ' | X“01”;+-----------------------+ | _ 二进制X 40 ' | X ' 01 ' | +-----------------------+ | 一个 | +-----------------------+
填充或剥离也可以使用以下函数来完成LPAD ()
那RPAD ()
那SUBSTR ()
,或投()
。在这种情况下,表达论点不再是所有的文字和_binary
变得不必要。例子:
MySQL>选择LPAD(X'40',2,X'00')|X'0001';+ ------------------------------ + |LPAD(X'40',2,X'00')|X'0001'|+ ------------------------------ + |a |+ ----------------------------- + MySQL>选择X'40'|substr(x'0001',2,1);+ ---------------------------- + | X'40' | SUBSTR(X'0001', 2, 1) | +-------------------------------+ | A | +-------------------------------+
下面的示例演示了使用位操作来提取部分UUID值,在本例中是时间戳和IEEE 802节点号。这种技术要求每个提取的部分都需要位掩码。
将文本UUID转换为相应的16字节二进制值,以便可以在二进制字符串上下文中使用位操作进行操作:
mysql> set @uuid = uuid_to_bin('6ccd780c-baba-1026-9564-5b8c656024db');mysql>选择hex(@uuid);+ ------------------------------- + |十六进制(@UUID)|+ ------------------------------- + |6CCD780CBABA102695645B8C656024DB |+ --------------------------------
为值的时间戳和节点号部分构造位掩码。时间戳由前三部分组成(64位,0 ~ 63位),最后一部分是节点号(48位,80 ~ 127位)。
mysql> SET @ts_mask = CAST(X' ffffffffffffff ' AS BINARY(16));mysql> SET @node_mask = CAST(X' ffffffffff ' AS BINARY(16)) >> 80;mysql >选择十六进制(@ts_mask);+----------------------------------+ | 十六进制(@ts_mask ) | +----------------------------------+ | FFFFFFFFFFFFFFFF0000000000000000 | +----------------------------------+ mysql >选择十六进制(@node_mask);+----------------------------------+ | 十六进制(@node_mask ) | +----------------------------------+ | 00000000000000000000 ffffffffffff | +----------------------------------+
这演员(......作为二进制(16))
这里使用函数,因为掩码必须与应用程序的UUID值相同。可以使用其他功能生产相同的结果以将掩模填充到所需的长度:
SET @ts_mask= RPAD(X' ffffffffffffff ', 16, X'00');SET @node_mask = LPAD(X' ffffffffff ', 16, X'00');
使用掩码提取时间戳和节点编号部分:
mysql> SELECT HEX(@uuid & @ts_mask) AS 'timestamp part';+----------------------------------+ | 时间戳的部分 | +----------------------------------+ | 6 ccd780cbaba10260000000000000000 | +----------------------------------+ mysql >选择十六进制(@uuid & @node_mask)作为节点部分的;+----------------------------------+ | 部分节点 | +----------------------------------+ | 000000000000000000005 b8c656024db | +----------------------------------+
UUID_TO_BIN()
占用标志,导致产生的二进制UUID值中的某些位重新排列。如果使用该标志,请相应地修改提取掩码。
下一个示例使用位操作提取IPv6地址的网络和主机部分。假设网络部分的长度为80位。那么主机部分的长度为128−80 = 48位。为了提取地址的网络和主机部分,将其转换为二进制字符串,然后在二进制字符串上下文中使用位运算。
将文本IPv6地址转换为对应的二进制字符串:
mysql> SET @ip = INET6_ATON('fe80::219:d1ff:fe91:1a72');
定义位的网络长度:
mysql> SET @net_len = 80;
通过左移或右移全1地址来构造网络和主机掩码。要做到这一点,请从地址开始::
,这是所有0的简写,你可以把它转换成二进制字符串,如下所示:
mysql>选择hex(Inet6_aton('::'))为“所有零”;+ ------------------------------- + |所有零|+ ------------------------------- + |00000000000000000000000000000000 |+ --------------------------------
要产生互补价值(所有),使用〜
运算符反转比分:
mysql> SELECT HEX(~INET6_ATON('::')) AS 'all ones';+----------------------------------+ | 所有的 | +----------------------------------+ | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF | +----------------------------------+
将左侧或右侧的All-Ones值转移以生成网络和主机掩码:
mysql >设置@net_mask = ~ INET6_ATON ('::') << ( 128 - @net_len);mysql >设置@host_mask = ~ INET6_ATON ('::') >> @ net_len;
显示掩码以验证它们是否涵盖了地址的正确部分:
MySQL>选择Inet6_ntoA(@NET_MASK)作为“网络掩码”;+ -------------------------- + |网络面具|+ -------------------------- + |FFFF:FFFF:FFFF:FFFF:FFFF :: |+ --------------------------+ ---------------------- + |主机面具|+ ---------------------- + |:: FFFF:255.255.255.255 | +------------------------+
提取并显示地址的网络和主机部分:
mysql> SET @net_part = @ip & @net_mask;mysql> SET @host_part = @ip & @host_mask;mysql> SELECT INET6_NTOA(@net_part) AS '网络部分';+-----------------+ | 网络部分 | +-----------------+ | fe80:: 219:0:0:0 | +-----------------+ mysql >选择INET6_NTOA (@host_part)的主机部分;+------------------+ | 主机部分 | +------------------+ | :: d1ff: fe91:1a72 | +------------------+
前面的示例使用了以下位操作:〜
),左移(<<
)和按位和(&
)。
剩下的讨论提供了关于每一组位操作的参数处理的详细信息,更多关于位操作中的文字值处理的信息,以及MySQL 8.0和旧MySQL版本之间潜在的不兼容性。
为了&
那|
,^
位操作,结果类型取决于参数是否被评为二进制字符串或数字:
当参数具有二进制字符串类型,且其中至少有一个不是十六进制字面值、位字面值或时,就会发生二进制字符串求值
零
文字。否则将发生数值计算,必要时将参数转换为无符号64位整数。二进制字符串评估生成与参数相同长度的二进制字符串。如果参数的长度不等,则
er_invalid_bitwise_operands_size.
发生错误。数字评估生成无符号64位整数。
数字评估的例子:
mysql> SELECT 64 | 1, X'40' | X'01';+--------+---------------+ | 64 | 1 | X 40 ' | X ' 01 ' | +--------+---------------+ | 65 | 65 | +--------+---------------+
二进制字符串评估的例子:
mysql> SELECT _binary X'40' | X'01';+-----------------------+ | _ 二进制X 40 ' | X ' 01 ' | +-----------------------+ | 一个 | +-----------------------+ mysql >设置@var1 = X 40, @var2 = X“01”;mysql> SELECT @var1 | @var2;+---------------+ | @ var1 | @var2 | +---------------+ | 一个 | +---------------+
为了〜
那<<
,>>
Bit操作时,结果类型取决于Bit参数是作为二进制字符串还是数字计算:
在比特参数具有二进制字符串类型时发生二进制字符串评估,而不是十六进制文字,位文字或
零
文字。否则,数值评估发生,参数转换为必要时转换为无符号64位整数。二进制字符串计算产生一个与bit参数长度相同的二进制字符串。数字评估生成无符号64位整数。
对于Shift操作,无论参数类型如何,位会丢失值的末尾的位移,而不会警告。特别地,如果换档计数更大或等于位参数中的比特数,则结果中的所有位为0。
数字评估的例子:
mysql>选择〜0,44 << 2,x'40'<< 2;+ ----------------------------- + ------------ + |〜0 |64 << 2 |X'40'<< 2 |+ ----------------------------- + ------------ + |18446744073709551615 |256 |256 |+ ---------------------------- + ------------ +
二进制字符串评估的例子:
MySQL>选择十六进制(_Binary X'1111000022220000'>> 16);+ ------------------------------------十六进制(_Binary X'1111000022220000'>> 16)|+ ------------------------------------00001111000022222 |+ ----------------------------------- + MySQL>选择十六进制(_binary x'1111000022220000'<< 16);+ ------------------------------------十六进制(_BINARY X'1111000022220000'<< 16)|+ ------------------------------------0000222200000000 | +----------------------------------------+ mysql> SET @var1 = X'F0F0F0F0'; mysql> SELECT HEX(~@var1); +-------------+ | HEX(~@var1) | +-------------+ | 0F0F0F0F | +-------------+
这BIT_COUNT ()
函数始终返回无符号64位整数,或零
如果参数是零
。
mysql>选择bit_count(127);+ ---------------- + |bit_count(127)|+ ---------------- + |7 |+ --------------- + MySQL> Select Bit_Count(B'010101'),Bit_Count(_Binary B'010101');+ ------------------------------------------------ + |bit_count(b'010101')|bit_count(_binary b'010101')|+ ------------------------------------------------ + | 3 | 3 | +----------------------+------------------------------+
为了bit_and()
那bit_or()
,BIT_XOR ()
位函数,结果类型取决于函数参数值是否被评估为二进制字符串或数字:
当参数值具有二进制字符串类型,且参数不是十六进制字面值、位字面值或
零
文字。否则将发生数值计算,必要时将参数值转换为无符号64位整数。二进制字符串计算产生一个与参数值长度相同的二进制字符串。如果参数值的长度不相等,则
er_invalid_bitwise_operands_size.
发生错误。如果参数大小超过511字节,则er_invalid_bitwise_aggregate_operands_size.
发生错误。数字评估生成无符号64位整数。
零
除非所有值都是,否则值不会影响结果零
。在这种情况下,结果是具有与参数值的长度相同的中性值(所有位1bit_and()
,所有位0 forbit_or()
,BIT_XOR ()
)。
例子:
mysql>创建表t(group_id int,var边值(6));mysql>插入t值(1,null);mysql>插入t值(1,null);mysql>插入t值(2,null);mysql>插入t值(2,x'1234');mysql>插入t值(2,x'ff34');MySQL>选择十六进制(Bit_and(A)),HEX(Bit_or(A)),来自T组的HEX(Bit_xor(A))由Group_ID;+ ---------------- + ------------------------------ + |十六进制(Bit_and(A))|十六进制(Bit_or(A))| HEX(BIT_XOR(a)) | +-----------------+----------------+-----------------+ | FFFFFFFFFFFF | 000000000000 | 000000000000 | | 1234 | FF34 | ED00 | +-----------------+----------------+-----------------+
对于向后兼容性,MySQL 8.0在所有位参数是十六进制文字,BIT文字的情况下评估数字上下文中的位操作,或零
文字。也就是说,如果所有位参数都是未被残疾的十六进制文字,bit文字,或者,则对二进制字符串位参数的位操作不使用二进制字符串评估零
文字。(如果他们写的话,这不适用于这些文字_binary
介绍者,二进制
操作员,或其他方式明确指定为二进制字符串的方法。)
上面描述的文字处理与MySQL 8.0之前的版本相同。例子:
这些位操作在数字上下文中评估文字并生成一个
长整型数字
结果:b'0001' | b'0010' X'0008' << 8
这些位操作评估
零
在数字上下文中并生成一个长整型数字
结果有一个零
值:null&null null >> 4
在MySQL 8.0中,你可以通过显式地指明至少有一个参数是二进制字符串来执行这些操作:
_binary b'0001'|B'0010'_binary x'0008'<< 8二进制null&null二进制null >> 4
最后两个表达的结果是零
,就像没有二进制
操作符,但结果的数据类型是二进制字符串类型而不是整数类型。
由于位操作可以在MySQL 8.0中本地处理二进制字符串参数,因此某些表达式在MySQL 8.0中产生不同的结果而不是5.7。要注意的五种有问题的表达式类型是:
nonliteral_binary.{&|^}二进制二进制{&|^}nonliteral_binary.nonliteral_binary.{<< >>}任何事物〜nonliteral_binary.AGGR_BIT_FUNC(nonliteral_binary.)
这些表达式返回长整型数字
在MySQL 5.7中,二进制字符串在8.0。
符号的解释:
{
:应用于给定表达式类型的操作符列表。op1.
OP2.
…}二进制
:任何类型的二进制字符串参数,包括十六进制文字,位文字,或零
文字。nonliteral_binary.
:一个参数,它是除了十六进制文字,位文字的二进制字符串值,或者零
文字。AGGR_BIT_FUNC
:一个接受位值参数的聚合函数:bit_and()
那bit_or()
那BIT_XOR ()
。
有关如何在MySQL 5.7中准备的信息,以获取MySQL 5.7和8.0之间的潜在不兼容,请参阅位函数和操作符,在MySQL 5.7参考手册。
下面的列表描述了可用的位函数和操作符:
位或。
结果类型取决于参数是否被评估为二进制字符串或数字:
当参数具有二进制字符串类型,且其中至少有一个不是十六进制字面值、位字面值或时,就会发生二进制字符串求值
零
文字。否则将发生数值计算,必要时将参数转换为无符号64位整数。二进制字符串评估生成与参数相同长度的二进制字符串。如果参数的长度不等,则
er_invalid_bitwise_operands_size.
发生错误。数字评估生成无符号64位整数。
有关更多信息,请参阅本节中的介绍性讨论。
mysql>选择29 |15;- > 31 mysql>选择_binary x'40404040'|x'01020304';- >'abcd'
按位和。
结果类型取决于参数是否被评估为二进制字符串或数字:
当参数具有二进制字符串类型,且其中至少有一个不是十六进制字面值、位字面值或时,就会发生二进制字符串求值
零
文字。否则将发生数值计算,必要时将参数转换为无符号64位整数。二进制字符串评估生成与参数相同长度的二进制字符串。如果参数的长度不等,则
er_invalid_bitwise_operands_size.
发生错误。数字评估生成无符号64位整数。
有关更多信息,请参阅本节中的介绍性讨论。
mysql>选择29&15;- > 13 mysql>选择hex(_binary x'ff'&b'11110000');- >'f0'
按位xor。
结果类型取决于参数是否被评估为二进制字符串或数字:
当参数具有二进制字符串类型,且其中至少有一个不是十六进制字面值、位字面值或时,就会发生二进制字符串求值
零
文字。否则将发生数值计算,必要时将参数转换为无符号64位整数。二进制字符串评估生成与参数相同长度的二进制字符串。如果参数的长度不等,则
er_invalid_bitwise_operands_size.
发生错误。数字评估生成无符号64位整数。
有关更多信息,请参阅本节中的介绍性讨论。
mysql> SELECT 1 ^ 1;-> 0 mysql> SELECT 1 ^ 0-> 1 mysql> SELECT 11 ^ 3;-> 8 mysql> SELECT HEX(_binary X' fedc ' ^ X'1111');——>“EFCD”
转移一个龙龙(
长整型数字
)数字或二进制字符串的左边。结果类型取决于bit参数是作为二进制字符串还是数字进行计算:
在比特参数具有二进制字符串类型时发生二进制字符串评估,而不是十六进制文字,位文字或
零
文字。否则,数值评估发生,参数转换为必要时转换为无符号64位整数。二进制字符串计算产生一个与bit参数长度相同的二进制字符串。数字评估生成无符号64位整数。
无论参数类型如何,移离值末端的位都将丢失,没有警告。特别地,如果换档计数更大或等于位参数中的比特数,则结果中的所有位为0。
有关更多信息,请参阅本节中的介绍性讨论。
mysql> SELECT 1 << 2;mysql> SELECT HEX(_binary X'00FF00FF00FF' << 8);——>“FF00FF00FF00”
转移一个龙龙(
长整型数字
)右侧的数字或二进制字符串。结果类型取决于bit参数是作为二进制字符串还是数字进行计算:
在比特参数具有二进制字符串类型时发生二进制字符串评估,而不是十六进制文字,位文字或
零
文字。否则,数值评估发生,参数转换为必要时转换为无符号64位整数。二进制字符串计算产生一个与bit参数长度相同的二进制字符串。数字评估生成无符号64位整数。
无论参数类型如何,移离值末端的位都将丢失,没有警告。特别地,如果换档计数更大或等于位参数中的比特数,则结果中的所有位为0。
有关更多信息,请参阅本节中的介绍性讨论。
mysql> SELECT 4 >> 2;-> 1 mysql> SELECT HEX(_binary X'00FF00FF00FF' >> 8);- > 0000年ff00ff00
反转所有位。
结果类型取决于bit参数是作为二进制字符串还是数字进行计算:
在比特参数具有二进制字符串类型时发生二进制字符串评估,而不是十六进制文字,位文字或
零
文字。否则,数值评估发生,参数转换为必要时转换为无符号64位整数。二进制字符串计算产生一个与bit参数长度相同的二进制字符串。数字评估生成无符号64位整数。
有关更多信息,请参阅本节中的介绍性讨论。
mysql> SELECT 5 & ~1;-> 4 mysql> SELECT HEX(~X'0000FFFF1111EEEE');——>“FFFF0000EEEE1111”
返回参数中设置的位数
N
作为无符号64位整数,或零
如果参数是零
。MySQL> Select Bit_Count(64),Bit_Count(二进制64);- > 1,7 mysql> select bit_count('64'),bit_count(_binary'64');- > 1,7 mysql> Select Bit_count(x'40'),bit_count(_binary x'40');- > 1,1