MySQL位及位运算研究

数据库 专栏收录该内容
95 篇文章 0 订阅

 

下面是官方给出的定义:

位-值类型-位

这个BIT数据类型用于存储位值。一种BIT(M)启用存储M-位值。M范围从1到64。

若要指定位值,b'value'可以使用符号。value是使用零和1编写的二进制值。例如,b'111'b'10000000'分别代表7和128。 

如果将值赋值给BIT(M)列小于M位长,该值在左边用零填充。例如,分配一个b'101'转到BIT(6)列实际上与分配b'000101'.

NDB集群所有数据的最大组合大小。BIT在给定的列中使用的列NDB表不得超过4096位。

注意上面的M的最大值是64.

 

 

 

原本想自己写点东西,结果发现官方文档介绍的挺全的,直接引用吧。

 

 

9.1.5位值文字

位值文字是使用b'val'0bval符号。val是使用零和1编写的二进制值。任何前导字母b不重要。领军0b是区分大小写的,不能写为0B.

法律位值文字:

b'01'
B'01'
0b01

非法位值文字:

b'2'    (2 is not a binary digit)
0B01    (0B must be written as 0b)

默认情况下,位值文字是二进制字符串:

mysql> SELECT b'1000001', CHARSET(b'1000001');
+------------+---------------------+
| b'1000001' | CHARSET(b'1000001') |
+------------+---------------------+
| A          | binary              |
+------------+---------------------+
mysql> SELECT 0b1100001, CHARSET(0b1100001);
+-----------+--------------------+
| 0b1100001 | CHARSET(0b1100001) |
+-----------+--------------------+
| a         | binary             |
+-----------+--------------------+

位值文字可能有一个可选的字符集引导者和COLLATE子句,将其指定为使用特定字符集和排序规则的字符串:

[_charset_name] b'val' [COLLATE collation_name]

例子:

SELECT _latin1 b'1000001';
SELECT _utf8 0b1000001 COLLATE utf8_danish_ci;

示例使用b'val'符号,但是0bval符号也允许介绍。有关介绍人的信息,请参阅第10.3.8节,“字符集介绍人”.

在数字上下文中,MySQL将一点文字视为整数。若要确保对位文字进行数值处理,请在数字上下文中使用它。这样做的方法包括添加0或使用CAST(... AS UNSIGNED)...例如,在默认情况下,分配给用户定义变量的位文字是二进制字符串.若要将值赋值为数字,请在数字上下文中使用它:

mysql> SET @v1 = b'1100001';
mysql> SET @v2 = b'1100001'+0;
mysql> SET @v3 = CAST(b'1100001' AS UNSIGNED);
mysql> SELECT @v1, @v2, @v3;
+------+------+------+
| @v1  | @v2  | @v3  |
+------+------+------+
| a    |   97 |   97 |
+------+------+------+

空位值(b'')计算结果为零长度二进制字符串。转换成一个数字,它产生0:

mysql> SELECT CHARSET(b''), LENGTH(b'');
+--------------+-------------+
| CHARSET(b'') | LENGTH(b'') |
+--------------+-------------+
| binary       |           0 |
+--------------+-------------+
mysql> SELECT b''+0;
+-------+
| b''+0 |
+-------+
|     0 |
+-------+

位值表示法便于指定要分配给的值。BIT栏:

mysql> CREATE TABLE t (b BIT(8));
mysql> INSERT INTO t SET b = b'11111111';
mysql> INSERT INTO t SET b = b'1010';
mysql> INSERT INTO t SET b = b'0101';

结果集中的位值作为二进制值返回,可能显示得不好。若要将位值转换为可打印形式,请在数值上下文中使用该值,或使用转换函数(如BIN()HEX()...转换后的值中不显示高阶0位数.

mysql> SELECT b+0, BIN(b), OCT(b), HEX(b) FROM t;
+------+----------+--------+--------+
| b+0  | BIN(b)   | OCT(b) | HEX(b) |
+------+----------+--------+--------+
|  255 | 11111111 | 377    | FF     |
|   10 | 1010     | 12     | A      |
|    5 | 101      | 5      | 5      |
+------+----------+--------+--------+

 

 

12.12位函数和运算符

表12.16位函数和运算符

名字描述
BIT_COUNT()返回设置的位数。
&按位和
~位反演
|按位或
^位异或
<<左移
>>右移

 

位函数和运算符包括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行为:位函数和运算符允许二进制字符串类型参数(BINARYVARBINARY,以及BLOB),使它们能够接受参数并生成大于64位的返回值。因此,MySQL5.7中对二进制参数的位操作可能会在MySQL8.0中产生不同的结果。为了提前通知这种行为上的潜在变化,服务器将为MySQL8.0中未将二进制参数转换为整数的位操作生成警告(MySQL5.7.11)。这些警告提供了重写受影响语句的机会。要显式地生成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)

为了避免受影响的语句在升级到MySQL8.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)

随着语句的重写如图所示,MySQL8.0尊重将二进制参数视为整数的意图,并产生与5.7中相同的结果。另外,将语句从MySQL 5.7复制到8.0并不会在不同的服务器上产生不同的结果。

无法重写的受影响语句在升级和复制方面会遇到以下潜在问题:

  • 在升级到MySQL8.0之后,该语句可能返回不同的结果。

  • 从旧版本复制到MySQL8.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
    
  • <<

    移动一个龙龙(BIGINT)左边的号码。

    结果是一个无符号64位整数.该值被截断为64位。特别是,如果移位计数大于或等于无符号64位数的宽度,则结果为零。

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

    移动一个龙龙(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

 

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值