MySQL尾部空格处理与哪些设置有关? 字符集PAD SPACE与NO PAD属性的区别、MySQL字段尾部有空格为什么也能查询出来?

文章目录

  • 一、问题背景
  • 二、字符集PAD_ATTRIBUTE属性(补齐属性)
    • 2.2、PAD SPACE与NO PAD的具体意义
  • 三、CHAR类型尾部空格的处理
  • 四、其他问题
    • 4.1、在PAD SPACE属性时如何实现精准查询
  • 五、总结

以下内容基于MySQL8.0进行讲解

一、问题背景

一次查询中发现查询出来的内容结尾有空格,跟我预期的结果不一致,由此引发出对本篇的整理。

案例如下:

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(10)  CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '姓名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1;

insert into user values
(null,'123456789     '), -- 数字后面有9个空格
(null,'张三   '), -- 名字后面有3个空格 
(null,'李四   '),-- 名字后面有3个空格
(null,'王五')
;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

以上内容可以看出

  1. 当结尾是由于空格导致的超长插入时不会报错,会自动截取掉多余的空格。
  2. 当查询时尾部有空格时,也能匹配上。

以下我们就研究一下MySQL尾部空格处理与哪些设置有关

二、字符集PAD_ATTRIBUTE属性(补齐属性)

先给出结论: MySQL尾部空格处理与字符集有关,具体的是看字符集的Pad Attributes属性

information_schema> SELECT *  FROM INFORMATION_SCHEMA.COLLATIONS WHERE CHARACTER_SET_NAME = 'utf8mb4' and COLLATION_NAME='utf8mb4_general_ci'; 
+--------------------+--------------------+----+------------+-------------+---------+---------------+
| COLLATION_NAME     | CHARACTER_SET_NAME | ID | IS_DEFAULT | IS_COMPILED | SORTLEN | PAD_ATTRIBUTE |
+--------------------+--------------------+----+------------+-------------+---------+---------------+
| utf8mb3_general_ci | utf8mb3            | 33 | Yes        | Yes         | 1       | PAD SPACE     |
+--------------------+--------------------+----+------------+-------------+---------+---------------+
1 row in set


information_schema> SELECT *  FROM INFORMATION_SCHEMA.COLLATIONS WHERE CHARACTER_SET_NAME = 'utf8mb4' and COLLATION_NAME='utf8mb4_0900_ai_ci'; 
+--------------------+--------------------+-----+------------+-------------+---------+---------------+
| COLLATION_NAME     | CHARACTER_SET_NAME | ID  | IS_DEFAULT | IS_COMPILED | SORTLEN | PAD_ATTRIBUTE |
+--------------------+--------------------+-----+------------+-------------+---------+---------------+
| utf8mb4_0900_ai_ci | utf8mb4            | 255 | Yes        | Yes         | 0       | NO PAD        |
+--------------------+--------------------+-----+------------+-------------+---------+---------------+
1 row in set

可以看到二者在 PAD_ATTRIBUTE 的上差别。

在这里插入图片描述
MySQL的排序规则有一个属性Pad Attributes属性,这个属性的设置会影响数据库如何处理尾部空格(是否忽略尾部空格),如下官方文档描述

Collation Pad Attributes

Collations based on UCA 9.0.0 and higher are faster than collations based on UCA versions prior to 9.0.0. They also have a pad attribute of NO PAD, in contrast to PAD SPACE as used in collations based on UCA versions prior to 9.0.0. For comparison of nonbinary strings, NO PAD collations treat spaces at the end of strings like any other character (see Trailing Space Handling in Comparisons).

Comparison of nonbinary string values (CHAR, VARCHAR, and TEXT) that have a NO PAD collation differ from other collations with respect to trailing spaces. For example, 'a' and 'a ' compare as different strings, not the same string. This can be seen using the binary collations for utf8mb4. The pad attribute for utf8mb4_bin is PAD SPACE, whereas for utf8mb4_0900_bin it is NO PAD. Consequently, operations involving utf8mb4_0900_bin do not add trailing spaces, and comparisons involving strings with trailing spaces may differ for the two collations

官方文档,关于比较中尾部空格处理介绍如下:

Trailing Space Handling in Comparisons
MySQL collations have a pad attribute, which has a value of PAD SPACE or NO PAD:
• Most MySQL collations have a pad attribute of PAD SPACE.
• The Unicode collations based on UCA 9.0.0 and higher have a pad attribute of NO PAD; see Section 10.10.1, “Unicode Character Sets”.
For nonbinary strings (CHAR, VARCHAR, and TEXT values), the string collation pad attribute determines treatment in comparisons of trailing spaces at the end of strings:
• For PAD SPACE collations, trailing spaces are insignificant in comparisons; strings are compared without regard to trailing spaces.
• NO PAD collations treat trailing spaces as significant in comparisons, like any other character.
The differing behaviors can be demonstrated using the two utf8mb4 binary collations, one of which is PAD SPACE, the other of which is NO PAD.

2.2、PAD SPACE与NO PAD的具体意义

  • PAD SPACE:在排序和比较运算中,忽略字符串尾部空格。
  • NO PAD:在排序和比较运算中,字符串尾部空格当成普通字符,不能忽略。

官方文档中也要一个例子简单说明,两者比较时,如何处理尾部空格。如下所示,相当直观、明了:

mysql> SELECT 'a ' = 'a'  COLLATE utf8mb4_general_ci;
+------------+
| 'a ' = 'a' |
+------------+
|          1 |
+------------+

mysql> SELECT 'a ' = 'a'  COLLATE utf8mb4_0900_ai_ci;
+------------+
| 'a ' = 'a' |
+------------+
|          0 |
+------------+

以上示例可以看出不同的字符集对于尾部空格的处理方式也不同。最上面的示例中name字段我们用的是 utf8mb4_general_ci字符集,即Pad Attributes属性为PAD SPACE,所以忽略尾部空格,不管是字段存储中带空格,还是查询语句where条件后面带空格都能匹配上。


接下来我们用utf8mb4_0900_ai_ci字符集,即Pad Attributes属性为NO PAD测试一下:
CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(10)  CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '姓名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1;

insert into user values
(null,'123456789     '), -- 数字后面有9个空格
(null,'张三   '), -- 名字后面有3个空格 
(null,'李四   '),-- 名字后面有3个空格
(null,'王五')
;

在这里插入图片描述
我们发现当属性为NO PAD时是不会忽略尾部的空格的,所以where后面不带空格时查询不出来内容。

另外,我们这里测试的是VARCHAR类型,如果字段类型为CHAR呢?

三、CHAR类型尾部空格的处理

其实呢,对于CHAR类型和VARCHA类型,它们的存储略有区别:

CHAR(N):当插入的字符数小于N,它会在字符串的右边补充空格,直到总字符数达到N再进行存储;当查询返回数据时默认会将字符串尾部的空格去掉,除非SQL_MODE设置PAD_CHAR_TO_FULL_LENGTH。

VARCHAR(N):当插入的字符数小于N,它不会在字符串的右边补充空格,insert内容原封不动的进行存储;如果原本字符串右边有空格,在存储和查询返回时都会保留空格

The length of a CHAR column is fixed to the length that you declare when you create the table. The length can be any value from 0 to 255. When CHAR values are stored, they are right-padded with spaces to the specified length. When CHAR values are retrieved, trailing spaces are removed unless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.

PAD_CHAR_TO_FULL_LENGTH

By default, trailing spaces are trimmed from CHAR column values on retrieval. If PAD_CHAR_TO_FULL_LENGTH is enabled, trimming does not occur and retrieved CHAR values are padded to their full length. This mode does not apply to VARCHAR columns, for which trailing spaces are retained on retrieval.

Note: As of MySQL 8.0.13, PAD_CHAR_TO_FULL_LENGTH is deprecated. Expect it to be removed in a future version of MySQL.

注意事项:

  • PAD_CHAR_TO_FULL_LENGTH只影响CHAR类型,不影响VARCHAR类型。
  • MySQL 8.0.13后,PAD_CHAR_TO_FULL_LENGTH参数过时/废弃了。这个参数可能在后续的MySQL版本中被移除。

当前版本(MySQL 8.0.33)中,暂时还可以在SQL_MODE中设置这个参数,不过默认不会设置此参数。那么我们来测试验证一下:

drop table test;
create table test(id int not null, name char(10)  );
insert into test(id , name) values(1, null);
insert into test(id , name) values(2, '');
insert into test(id , name) values(3, ' '); -- 包含一个空格
insert into test(id , name) values(4, '  ');-- 包含两个空格

mysql> show variables like 'sql_mode'\G
*************************** 1. row ***************************
Variable_name: sql_mode
        Value: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
1 row in set (0.00 sec)

mysql> --如下所示,SQL_MODE没有设置PAD_CHAR_TO_FULL_LENGTH时,查询返回数据时默认会将字符串尾部的空格去掉,所以你看到长度为零
mysql> select id, length(name), char_length(name),hex(name) from test;
+----+--------------+-------------------+-----------+
| id | length(name) | char_length(name) | hex(name) |
+----+--------------+-------------------+-----------+
|  1 |         NULL |              NULL | NULL      |
|  2 |            0 |                 0 |           |
|  3 |            0 |                 0 |           |
|  4 |            0 |                 0 |           |
+----+--------------+-------------------+-----------+
4 rows in set (0.00 sec)

mysql>

那么我们手工设置一下当前会话的SQL_MODE,然后对比测试一下:

mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show variables like 'sql_mode';
+---------------+-------------------------+
| Variable_name | Value                   |
+---------------+-------------------------+
| sql_mode      | PAD_CHAR_TO_FULL_LENGTH |
+---------------+-------------------------+
1 row in set (0.01 sec)

mysql> select id, length(name), char_length(name),hex(name) from test;
+----+--------------+-------------------+----------------------------------+
| id | length(name) | char_length(name) | hex(name)                        |
+----+--------------+-------------------+----------------------------------+
|  1 |         NULL |              NULL | NULL                             |
|  2 |           10 |                10 | 20202020202020202020 |
|  3 |           10 |                10 | 20202020202020202020 |
|  4 |           10 |                10 | 20202020202020202020 |
+----+--------------+-------------------+----------------------------------+
4 rows in set (0.00 sec)

mysql>

通过上面的分析讲述,我们知道当数据库的排序规则的Pad Attributes属性为NO PAD时,此时SQL_MODE的PAD_CHAR_TO_FULL_LENGTH设置与否将会影响查询结果。我们新建一个test2数据库,数据库排序规则为utf8mb4_0900_ai_ci,下面我们通过实验对比一下就知道了:

mysql> use test2;
Database changed
mysql> show variables like 'sql_mode'\G
*************************** 1. row ***************************
Variable_name: sql_mode
        Value: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
1 row in set (0.00 sec)

-- 对于CHAR类型,查询返回数据时默认会将字符串尾部的空格去掉,所以name=''会得到三条记录
mysql> select * from test where name='';
+----+------+
| id | name |
+----+------+
|  2 |      |
|  3 |      |
|  4 |      |
+----+------+
3 rows in set (0.01 sec)

mysql> select * from test where name=' ';
Empty set (0.00 sec)

mysql> select * from test where name='  ';
Empty set (0.00 sec)

mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show variables like 'sql_mode'\G
*************************** 1. row ***************************
Variable_name: sql_mode
        Value: PAD_CHAR_TO_FULL_LENGTH
1 row in set (0.01 sec)
-- SQL_MODE设置PAD_CHAR_TO_FULL_LENGTH。查询返回数据时,字符串尾部的空格不会去掉,此时,name字段时10个空格,故而下面查询条件查不到数据。
mysql>  select * from test where name='';
Empty set (0.01 sec)

mysql> select * from test where name=' ';
Empty set (0.00 sec)

mysql> select * from test where name='  ';
Empty set (0.00 sec)

mysql>

四、其他问题

4.1、在PAD SPACE属性时如何实现精准查询

上述案例中我们知道PAD_ATTRIBUTE属性为PAD SPACE时,在排序和比较运算中,忽略字符串尾部空格。此时where后面用等值匹配会匹配到结尾有空格的数据,那么如何实现精准查询呢?

drop table user;
CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(10)  CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '姓名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1;

insert into user values
(null,'张三'), -- 名字后无空格
(null,'张三 '),-- 名字后1个空格
(null,'张三  ')-- 名字后2个空格
;

在这里插入图片描述

方法一:like

select * from user where `name` like ?

在这里插入图片描述

方法二:BINARY

select * from user where `name` = BINARY ?

BINARY 不是函数,是类型转换运算符,它用来强制它后面的字符串为一个二进制字符串,可以理解成精确匹配

在这里插入图片描述

五、总结

关于MySQL的尾部空格是否忽略,以及对查询结果的影响,既跟数据库的排序规则有关(确切来说,是跟数据库排序规则的Pad Attributes有关),其实还跟字符类型和SQL_MODE是否设置PAD_CHAR_TO_FULL_LENGTH有关。

  1. MySQL的CHAR、VARCHAR、TEXT等字符串字段在等值比较(“=”)时,基于PAD SPACE校对规则,会忽略掉尾部的空格;
  2. 如果想要精确查询就不能用等值查询(“=”),而应改用LIKE或BINARY;








参考资料:

https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-sets.html

https://dev.mysql.com/doc/refman/8.0/en/charset-binary-collations.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/573736.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CTF之变量1

拿到题目发现是一个php代码,意思是用get方式获取args参数。 至于下面那个正则表达式怎么绕过暂且不知,但是题目最上面告诉我们lag In the variable ! (意思是flag就在变量中)。 那我们就传入全局变量globals(&#xf…

2024深圳杯(东北三省)数学建模C题完整论文讲解(含完整python代码及所有残骸音爆位置求解结果)

大家好呀,从发布赛题一直到现在,总算完成了2024深圳杯(东北三省数学建模联赛)A题多个火箭残骸的准确定位完整的成品论文。 本论文可以保证原创,保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊…

Java苍穹外卖01-开发环境搭建(Git、nginx)-Swagger-员工管理

一、开发环境搭建 1.项目架构 2.Git版本管理 在IDEA中可以一键搭建并commit,当Git远程仓库搭建后就可以push 3.前后端联调 Builder注解: 加了注解后就可以通过这样的方式创建对象 接收传入的是dto对象,传出去的对象为vo对象 4.nginx反向…

Java操作 elasticsearch 8.1,如何实现索引的重建?

🏆本文收录于「Bug调优」专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&…

网络协议深度解析:SSL、 TLS、HTTP和 DNS(C/C++代码实现)

在数字化时代,网络协议构成了互联网通信的基石。SSL、TLS、HTTP和DNS是其中最关键的几种,它们确保了我们的数据安全传输、网页的正确显示以及域名的正常解析。 要理解这些协议,首先需要了解网络分层模型。SSL和TLS位于传输层之上&#xff0c…

2000-2022年各区县农产品产量数据

2000-2022年县域农产品产量数据 1、时间:2000-2022年 2、指标:统计年度、县域名称、所属地级市、所属省份、地区编码ID、县域代码、产品种类或名称、单位、产量、 3、来源:统计局、县域统计年鉴、各区县政府官网 4、范围:具体…

网络编程——TCP的特性之自动重传/流量控制/拥塞控制,一篇说清楚

文章目录 1. ARQ自动重传协议1.1 停止等待ARQ1.2 连续ARQ1.3 总结 2. TCP的流量控制3. TCP的拥塞控制3.1 慢开始算法3.2 拥塞避免算法3.3 快重传算法3.4 快恢复算法 1. ARQ自动重传协议 自动重传请求(Automatic Repeat-reQuest),通过使用确认…

创新与乐趣的融合 —— 探索我们独家录音变音芯片在学舌玩具领域的应用

一:概述 学舌玩具,又称作复读玩具或模仿玩具,是一类设计用来录制人声并重复播放的互动式玩具。这类玩具以其能够模仿人类语音的特性而受到小朋友和宠物主人的喜爱。这些玩具通常具有以下特点和功能: 1. 录音和播放功能&#xff…

【C++航海王:追寻罗杰的编程之路】C++11(二)

目录 C11(上) 1 -> STL中的一些变化 2 -> 右值引用和移动语义 2.1 -> 左值引用和右值引用 2.2 -> 左值引用与右值引用比较 2.3 -> 右值引用使用场景与意义 2.4 -> 右值引用引用左值及其更深入的使用场景分析 2.5 -> 完美转发 C11(上) 1 -> STL…

4 -25

1 100个英语单词两篇六级阅读 2 cf补题; 3 仿b站项目看源码 debug分析业务。 上了一天课,晚上去健身。 物理备课,周六去上课腻。 五一回来毛泽东思想期末考试,概率论期中考试。

轻松搭建MySQL 8.0:Ubuntu上的完美指南

欢迎来到我的博客,代码的世界里,每一行都是一个故事 轻松搭建MySQL 8.0:Ubuntu上的完美指南 前言脚本编写脚本实现部署过程参数成功页面 彩蛋坏蛋解决方法 前言 在数字化时代,数据就像是我们的宝藏,而MySQL数据库就是…

【Qt 学习笔记】Qt常用控件 | 输入类控件 | Text Edit的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 输入类控件 | Text Edit的使用及说明 文章编号&#xff…

【题解】牛客挑战赛 71 - A 和的期望

原题链接 https://ac.nowcoder.com/acm/problem/264714 思路分析 快速幂求逆元 费马小定理: a MOD − 1 ≡ 1 ( m o d M O D ) a^{\text{MOD}-1} \equiv 1 \pmod{MOD} aMOD−1≡1(modMOD),可以转换为 a ⋅ a MOD − 2 ≡ 1 ( m o d M O D ) ① a \cd…

4.24总结

对部分代码进行了修改,将一些代码封装成方法,实现了头像功能,通过FileInputStream将本地的图片写入,再通过FileOutputStream拷贝到服务端的文件夹中,并将服务端的文件路径存入数据库中

Linear Blend Skinning (LBS)线性混合蒙皮

LBS是CG的基础概念之一。 Linear Blend Skinning: linearly blend the results of the vertex transformed rigidly with each bone. LBS:线性地混合顶点根据每个骨骼的刚性变形结果。 这个场景应用在哪里呢? 假如我们重建好一个人体,现在用…

水位监测识别摄像机

水位监测识别摄像机是一种利用人工智能技术进行水位监测的智能设备,其作用是监测水体的水位变化并识别潜在的水灾危险,以提供准确数据和及时预警,帮助保护人民生命财产安全。这种摄像机通过高清摄像头实时捕捉水体的图像,然后利用…

Coursera: An Introduction to American Law 学习笔记 Week 03: Property Law

An Introduction to American Law 本文是 https://www.coursera.org/programs/career-training-for-nevadans-k7yhc/learn/american-law 这门课的学习笔记。 文章目录 An Introduction to American LawInstructors Week 03: Property LawKey Property Law TermsSupplemental Re…

【yolo算法道路井盖检测】

yolo算法道路井盖检测 数据集和模型yolov8道路井盖-下水道井盖检测训练模型数据集pyqt界面yolov8道路井盖-下水道井盖检测训练模型数据集 算法原理 1. 数据集准备与增强 数据采集:使用行车记录仪或其他设备收集道路井盖的图像数据。数据标注:对收集到…

如何提交已暂存的更改到本地仓库?

文章目录 如何提交已暂存的更改到本地Git仓库?步骤1:确认并暂存更改步骤2:提交暂存的更改到本地仓库 如何提交已暂存的更改到本地Git仓库? 在Git版本控制系统中,当你对项目文件进行修改后,首先需要将这些更…

大学生在线考试|基于SprinBoot+vue的在线试题库系统系统(源码+数据库+文档)

大学生在线考试目录 基于SprinBootvue的在线试题库系统系统 一、前言 二、系统设计 三、系统功能设计 试卷管理 试题管理 考试管理 错题本 考试记录 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍&#…