相关文章推荐
阳刚的玉米  ·  TiDB Dashboard SQL ...·  1 周前    · 
帅气的生姜  ·  古代贪官的藏钱手段·  11 月前    · 
飞奔的企鹅  ·  搜索_常见问题·  1 年前    · 
打盹的大熊猫  ·  黑色圣经_百度百科·  1 年前    · 
不拘小节的太阳  ·  SOLIDWORKS ...·  1 年前    · 
📣

TiDB Cloud Serverless 现已更名为
TiDB Cloud Starter
!体验不变,名字焕新。
立即试用 →

位函数和操作符

TiDB 支持使用 MySQL 8.0 中提供的所有 位函数和操作符

位函数和操作符表

函数和操作符名 功能描述
BIT_COUNT() 返回参数二进制表示中为 1 的个数
& 按位与
~ 按位取反
| 按位或
^ 按位异或
<< 左移
>> 右移

BIT_COUNT()

BIT_COUNT(expr) 函数返回 expr 中为 1 的位数。

SELECT BIT_COUNT(b'00101001');
+------------------------+ | BIT_COUNT(b'00101001') | +------------------------+ | 3 | +------------------------+ 1 row in set (0.00 sec)

下面的示例与前面的类似,但使用的参数是十六进制数而非二进制数。 CONV() 函数用于将 0x29 从十六进制转换为二进制,可以看到 0x29 等价于二进制的 00101001

SELECT BIT_COUNT(0x29), CONV(0x29,16,2);
+-----------------+-----------------+ | BIT_COUNT(0x29) | CONV(0x29,16,2) | +-----------------+-----------------+ | 3 | 101001 | +-----------------+-----------------+ 1 row in set (0.01 sec)

BIT_COUNT(expr) 函数的一个常见用法是将子网掩码转换为 CIDR 表示法。在下面的示例中,子网掩码 255.255.255.0 被转换为其 CIDR 表示形式 24

SELECT BIT_COUNT(INET_ATON('255.255.255.0'));
+---------------------------------------+ | BIT_COUNT(INET_ATON('255.255.255.0')) | +---------------------------------------+ | 24 | +---------------------------------------+ 1 row in set (0.00 sec)

& (按位与)

& 操作符用于执行按位与 (bitwise AND) 操作。它会比较两个数中的对应位,如果两个对应位都是 1,则结果中的对应位为 1,否则为 0。

例如,对 1010 1100 进行按位与操作会返回 1000 ,因为在这两个数中只有最左边的第一位都是 1。

1010

在 SQL 中,可以这样使用 & 操作符:

SELECT CONV(b'1010' & b'1000',10,2);
+------------------------------+ | CONV(b'1010' & b'1000',10,2) | +------------------------------+ | 1000 | +------------------------------+ 1 row in set (0.00 sec)

你可以将 & 操作符与 INET_NTOA() INET_ATON() 函数结合在一起使用,对 IP 地址和网络掩码进行按位与操作,以获取网络地址。这对于判断多个 IP 地址是否属于同一网络非常有用。

在以下示例中,使用掩码 255.255.255.0 时,IP 地址 192.168.1.1 192.168.1.2 都属于同一网络 192.168.1.0/24

SELECT INET_NTOA(INET_ATON('192.168.1.1') & INET_ATON('255.255.255.0'));
+------------------------------------------------------------------+ | INET_NTOA(INET_ATON('192.168.1.1') & INET_ATON('255.255.255.0')) | +------------------------------------------------------------------+ | 192.168.1.0 | +------------------------------------------------------------------+ 1 row in set (0.00 sec)
SELECT INET_NTOA(INET_ATON('192.168.1.2') & INET_ATON('255.255.255.0'));
+------------------------------------------------------------------+ | INET_NTOA(INET_ATON('192.168.1.2') & INET_ATON('255.255.255.0')) | +------------------------------------------------------------------+ | 192.168.1.0 | +------------------------------------------------------------------+ 1 row in set (0.00 sec)

~ (按位取反)

~ 操作符用于对给定的值进行按位取反(bitwise NOT)操作。它会对给定值中的每一位进行取反:0 的位变为 1,1 的位变为 0。

在进行取反操作之前,它会先将给定的值扩展到 64 位。

以二进制数 1111000011110000 为例。当扩展到 64 位并进行取反后,其结果如下:

Original (16 bits): 1111000011110000 Expanded and inverted (64 bits): 1111111111111111111111111111111111111111111111110000111100001111

在 SQL 中,可以这样使用 ~ 操作符:

SELECT CONV(~ b'1111000011110000',10,2); +------------------------------------------------------------------+ | CONV(~ b'1111000011110000',10,2) | +------------------------------------------------------------------+ | 1111111111111111111111111111111111111111111111110000111100001111 | +------------------------------------------------------------------+ 1 row in set (0.00 sec)

如果需要对取反后的结果再次取反,可以再次应用 ~ 操作符。

SELECT CONV(~ b'1111111111111111111111111111111111111111111111110000111100001111',10,2);
+----------------------------------------------------------------------------------+ | CONV(~ b'1111111111111111111111111111111111111111111111110000111100001111',10,2) | +----------------------------------------------------------------------------------+ | 1111000011110000 | +----------------------------------------------------------------------------------+ 1 row in set (0.00 sec)

| (按位或)

| 操作符用于执行按位或 (bitwise OR) 操作。它会比较两个数中的对应位,如果至少有一个对应位为 1,则结果中的对应位为 1。

例如,对 1010 1100 进行按位或操作会返回 1110 ,因为在这两个数的前三位中,至少有一个数的对应位为 1。

1010 | 1100

在 SQL 中,可以这样使用 | 操作符:

SELECT CONV(b'1010' | b'1100',10,2);
+------------------------------+ | CONV(b'1010' | b'1100',10,2) | +------------------------------+ | 1110 | +------------------------------+ 1 row in set (0.00 sec)

^ (按位异或)

^ 操作符用于执行按位异或 (bitwise XOR) 操作。它会比较两个数中的对应位,如果对应位不同,则结果中的对应位为 1。

例如,对 1010 1100 进行按位异或操作会返回 0110 ,因为这两个数中的第二位和第三位都不同。

1010 ^ 1100

在 SQL 中,可以这样使用 ^ 操作符:

SELECT CONV(b'1010' ^ b'1100',10,2);
+------------------------------+ | CONV(b'1010' ^ b'1100',10,2) | +------------------------------+ | 110 | +------------------------------+ 1 row in set (0.00 sec)

需要注意的是,由于省略了前导零,结果会显示为 110 而不是 0110

<< (左移)

<< 操作符用于执行左移操作。它会将一个数中的所有位向左移动指定的位数,并用零填充右侧空出的位。

例如,下面的语句使用了 1<<n 将二进制数 1 向左移动了 n 位:

WITH RECURSIVE cte(n) AS ( SELECT 0 AS n UNION ALL SELECT 1+n FROM cte WHERE n<10 SELECT n,1<<n,LPAD(CONV(1<<n,10,2),11,0) FROM cte;
+------+------+----------------------------+ | n | 1<<n | LPAD(CONV(1<<n,10,2),11,0) | +------+------+----------------------------+ | 0 | 1 | 00000000001 | | 1 | 2 | 00000000010 | | 2 | 4 | 00000000100 | | 3 | 8 | 00000001000 | | 4 | 16 | 00000010000 | | 5 | 32 | 00000100000 | | 6 | 64 | 00001000000 | | 7 | 128 | 00010000000 | | 8 | 256 | 00100000000 | | 9 | 512 | 01000000000 | | 10 | 1024 | 10000000000 | +------+------+----------------------------+ 11 rows in set (0.00 sec)

>> (右移)

>> 操作符用于执行右移操作。它会将数中的所有位向右移动指定的位数,并用零填充左侧空出的位。

例如,下面的语句使用了 1024>>n 将数字 1024 (二进制为 10000000000 )向右移动了 n 位:

WITH RECURSIVE cte(n) AS ( SELECT 0 AS n UNION ALL SELECT n+1 FROM cte WHERE n<11 SELECT n,1024>>n,LPAD(CONV(1024>>n,10,2),11,0) FROM cte;
+------+---------+-------------------------------+ | n | 1024>>n | LPAD(CONV(1024>>n,10,2),11,0) | +------+---------+-------------------------------+ | 0 | 1024 | 10000000000 | | 1 | 512 | 01000000000 | | 2 | 256 | 00100000000 | | 3 | 128 | 00010000000 | | 4 | 64 | 00001000000 | | 5 | 32 | 00000100000 | | 6 | 16 | 00000010000 | | 7 | 8 | 00000001000 | | 8 | 4 | 00000000100 |