广告
返回顶部
首页 > 资讯 > 数据库 >解决MySQL Varchar 类型尾部空格的问题
  • 642
分享到

解决MySQL Varchar 类型尾部空格的问题

2024-04-02 19:04:59 642人浏览 独家记忆
摘要

目录背景原因详解char 和 varchar 的区别varchar 对于尾部空格的处理确定排序规则的 pad 属性背景 近期发现系统中某个输入框里如果输入xxx+空格的时候会出现异常

背景

近期发现系统中某个输入框里如果输入xxx+空格的时候会出现异常情况,经过排查发现在调用后端接口时会有两步操作,一是从数据库中查询到的数组中将与xxx+空格一致的元素剔除,二是根据xxx+空格数据库中查询对应的明细。

出现异常的原因是在剔除时未能剔除掉对应的元素,也就意味着xxx+空格对应的内容在数据库中不存在;但是在查询明细时还是查询到了,顿时感觉很费解,也就衍生出了这篇文章后续的内容。

原因

  • 开发人员在处理前端传过来的字符串时没有执行 trim(),所以导致与数组中元素匹配的时候没有匹配到,也就没能剔除对应的元素,"a".equals("a ") 的结果肯定是 false 嘛。

  • Mysql 在查询时会忽略掉字符串最后的空格,所以导致xxx+空格作为查询条件时和xxx为同一效果。

详解

对于第一条原因只能说是开发时疏漏,没什么可说的,我们着重了解下第二条,为什么 mysql 会忽略掉查询条件最后的空格。本文基于 Mysql 8.0.28,文章中有些内容是 MySQL 8.0 新增的,但主体也适用于 5.x 版本。

在探究之前我们需要准备下使用的数据库,毕竟实践出来的结果才是真实的,首先我们准备一个测试使用的数据库和表,结构如下,字符集和排序规则先选择比较常用的 utf8mb4 和 utf8mb4_unicode_ci,之后在表里插入两条数据:

mysql> desc test;
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| id           | int         | NO   | PRI | NULL    |       |
| name_char    | char(20)    | YES  |     | NULL    |       |
| name_varchar | varchar(20) | YES  |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
INSERT INTO `test` VALUES (1, 'char1', 'varchar1');
INSERT INTO `test` VALUES (2, 'char2     ', 'varchar2     ');

char 和 varchar 的区别

首先看一下官方对于 char 类型和 varchar 类型的介绍,以下内容摘自【11.3.2 The CHAR and VARCHAR Types】

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.
Values in VARCHAR columns are variable-length strings. The length can be specified as a value from 0 to 65,535. The effective maximum length of a VARCHAR is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used.

通过以上我们可以得知以下几部分内容:

  • char 类型长度为 0-255,varchar 类型长度为 0-65535,char 和 varchar 类型的长度其实还会受到内容长度的影响,这里我们不深究。

  • char 类型为定长字段,存储时会向右填充空格至声明的长度;varchar 类型为变长字段,存储时声明的只是可存储的最长内容,实际长度与内容有关。

  • 在 sql mode 中未开启 PAD_CHAR_TO_FULL_LENGTH 时,char 类型在查询时会在忽略尾部空格(关于 sql mode 的资料请移步【5.1.11 Server SQL Modes】,这里我们不深究)

下面的查询结果中第一行是都没有空格的结果,第二行是都带有 5 个空格的结果,可以看到 char 类型无论带不带空格都只会返回基本的字符。

mysql> select concat("(",name_char,")") name_char, concat("(",name_varchar,")") name_varchar from test;
+-----------+-----------------+
| name_char | name_varchar    |
+-----------+-----------------+
| (char1)   | (varchar1)      |
| (char2)   | (varchar2     ) |
+-----------+-----------------+
2 rows in set (0.01 sec)

第一行好理解,你存进去的时候没带空格,数据库自己填充上了空格,总不能查出来的结果还变了吧;第二行则是入库的时候字符串最后的字符和数据库填充的字符是同一种,查询的时候数据库怎么分得清是你自己填的还是它填的呢,直接一刀切。而 varchar 类型因为不会被填充,所以查询结果中完成的保留下了尾部空格。

varchar 对于尾部空格的处理

上节了解过 char 类型查询时会忽略尾部空格,但是在实际使用中发现 varchar 也有类似的规则,在查看文档时发现有以下一段内容,摘自【11.3.2 The CHAR and VARCHAR Types】

Values in CHAR, VARCHAR, and TEXT columns are sorted and compared according to the character set collation assigned to the column.
MySQL collations have a pad attribute of PAD SPACE, other than Unicode collations based on UCA 9.0.0 and higher, which have a pad attribute of NO PAD.

根据这一段描述,我们可以得知 char、varchar 和 text 内容的排序和比较过程受排序规则影响,在 UCA 9.0.0 之前 pad 属性默认为 PAD SPACE,而之后的默认属性为 NO PAD。

在官方文档中可以找到以下说明,摘自【Trailing Space Handling in Comparisons】

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.

这一段主要描述 char、varchar 和 text 类型在比较时,如果排序规则的 pad 属性为 PAD SPACE 则会忽略尾部空格,NO PAD 属性则不会,而这正解释了最初的问题。我们通过修改列的排序规则验证以下,首先看一下当前使用 PAD SPACE 时的查询结果。

mysql> show full columns from test;
+--------------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Field        | Type        | Collation          | Null | Key | Default | Extra | Privileges                      | Comment |
+--------------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| id           | int         | NULL               | NO   | PRI | NULL    |       | select,insert,update,references |         |
| name_char    | char(20)    | utf8mb4_unicode_ci | YES  |     | NULL    |       | select,insert,update,references |         |
| name_varchar | varchar(20) | utf8mb4_unicode_ci | YES  |     | NULL    |       | select,insert,update,references |         |
+--------------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
3 rows in set (0.01 sec)

mysql> select * from test where name_varchar = 'varchar2';
+----+-----------+---------------+
| id | name_char | name_varchar  |
+----+-----------+---------------+
|  2 | char2     | varchar2      |
+----+-----------+---------------+
1 row in set (0.01 sec)

可以看到在 PAD SPACE 属性下可以通过varchar2查询到varchar2,说明比较时忽略的尾部的空格,我们将 name_varchar 的排序规则切换为 UCA 9.0.0 以后版本再来看一下结果。

mysql> ALTER TABLE test CHANGE name_varchar name_varchar VARCHAR(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show full columns from test;
+--------------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Field        | Type        | Collation          | Null | Key | Default | Extra | Privileges                      | Comment |
+--------------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| id           | int         | NULL               | NO   | PRI | NULL    |       | select,insert,update,references |         |
| name_char    | char(20)    | utf8mb4_unicode_ci | YES  |     | NULL    |       | select,insert,update,references |         |
| name_varchar | varchar(20) | utf8mb4_0900_ai_ci | YES  |     | NULL    |       | select,insert,update,references |         |
+--------------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
3 rows in set (0.01 sec)

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

与预期一样,切换排序规则后,尾部空格参与比较,已经不能通过varchar2查询到varchar2了。

确定排序规则的 pad 属性

那接下来的问题是如何判断当前的排序规则是基于 UCA 9.0.0 之前还是之后的版本呢?其实在 mysql 8.x 版本中,排序规则保存在 infORMation_schema 库的 COLLATIONS 表中,可以通过以下语句查询对应的 pad 属性值,例如我们一开始选择的 utf8mb4_unicode_ci。

mysql> select collation_name, pad_attribute from information_schema.collations where collation_name = 'utf8mb4_unicode_ci';
+--------------------+---------------+
| collation_name     | pad_attribute |
+--------------------+---------------+
| utf8mb4_unicode_ci | PAD SPACE     |
+--------------------+---------------+
1 row in set (0.00 sec)

除了查询数据库以外,还可以通过排序规则的名称进行区别,在官方文档中有以下一段描述,摘自【Unicode Collation AlGorithm (UCA) Versions】

MySQL implements the xxx_unicode_ci collations according to the Unicode Collation Algorithm (UCA) described at Http://www.unicode.org/reports/tr10/. The collation uses the version-4.0.0 UCA weight keys: http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt. The xxx_unicode_ci collations have only partial support for the Unicode Collation Algorithm.

Unicode collations based on UCA versions higher than 4.0.0 include the version in the collation name. Examples:

  • utf8mb4_unicode_520_ci is based on UCA 5.2.0 weight keys (http://www.unicode.org/Public/UCA/5.2.0/allkeys.txt),

  • utf8mb4_0900_ai_ci is based on UCA 9.0.0 weight keys (http://www.unicode.org/Public/UCA/9.0.0/allkeys.txt).

可以看出,名称类似 xxx_unicode_ci 的排序规则是基于 UCA 4.0.0 的,而 xxx_520_ci 是基于 UCA 5.2.0,xxx_0900_ci 是基于 UCA 9.0.0 的。通过查询数据库验证,排序规则中包含 0900 字样的 pad 属性均为 NO PAD,符合以上描述。

需要注意的是 binary 排序规则的 pad 属性为 NO PAD,这里其实不是个例外,因为 char、varchar 和 text 类型都归类为nonbinary

到此这篇关于MySQLVarchar类型尾部空格的文章就介绍到这了,更多相关MySQLVarchar类型尾部空格内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: 解决MySQL Varchar 类型尾部空格的问题

本文链接: https://www.lsjlt.com/news/145105.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 解决MySQL Varchar 类型尾部空格的问题
    目录背景原因详解char 和 varchar 的区别varchar 对于尾部空格的处理确定排序规则的 pad 属性背景 近期发现系统中某个输入框里如果输入xxx+空格的时候会出现异常...
    99+
    2022-11-13
  • 详解Mysql查询条件中字符串尾部有空格也能匹配上的问题
    一、表结构 TABLE person id name 1 你 2 ...
    99+
    2022-10-18
  • vue如何解决空格和空行报错的问题
    目录解决空格和空行报错问题vue出现空格警告的原因解决空格和空行报错问题 到build文件夹下面的webpack.base.conf.js文件。 然后打开该文件,找到图下这段代码,...
    99+
    2022-11-13
  • Python字符串类型及格式化问题怎么解决
    这篇文章主要讲解了“Python字符串类型及格式化问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python字符串类型及格式化问题怎么解决”吧!一、字符串类型1)字符串是字符的序...
    99+
    2023-07-05
  • 如何解决MySQL存储时间类型选择的问题
    这篇文章主要为大家展示了“如何解决MySQL存储时间类型选择的问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决MySQL存储时间类型选择的问题”这篇文...
    99+
    2022-10-18
  • 怎么解决Oracle12c中空格引发的ORA-01516问题
    本篇内容介绍了“怎么解决Oracle12c中空格引发的ORA-01516问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读...
    99+
    2022-10-18
  • Dreamweaver如何解决网页制作中的空格问题
    小编给大家分享一下Dreamweaver如何解决网页制作中的空格问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Dreamweaver是一个非常简单易用但又功能...
    99+
    2023-06-08
  • 详解隐秘的 MySQL 类型转换问题详解
    目录1、问题开篇1、字符串类型查询2、数值型查询2、问题引申3、跟进探究3.1 什么是隐式类型转换?3.2 如何避免隐式类型转换?3.2.1 清楚转换规则3.2.2 使用内置函数显示转换3.2.3 类型保持一致3.3 字...
    99+
    2022-10-14
  • 详解隐秘的 MySQL 类型转换问题详解
    目录1、问题开篇1、字符串类型查询2、数值型查询2、问题引申3、跟进探究3.1 什么是隐式类型转换?3.2 如何避免隐式类型转换?3.2.1 清楚转换规则3.2.2 使用内置函数显示...
    99+
    2022-11-13
    MySQL 类型转换 MySQL 类型
  • mysql datetime类型精确到毫秒、微秒的问题怎么解决
    本篇内容主要讲解“mysql datetime类型精确到毫秒、微秒的问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“mysql datetime类型精确到毫秒、微秒...
    99+
    2023-07-05
  • 详解Java泛型中类型擦除问题的解决方法
    以前就了解过Java泛型的实现是不完整的,最近在做一些代码重构的时候遇到一些Java泛型类型擦除的问题,简单的来说,Java泛型中所指定的类型在编译时会将其去除,因此List&nbs...
    99+
    2022-11-13
  • 解决mysql的int型主键自增问题
    引入 我们在使用mysql数据库时,习惯使用int型作为主键,并设置为自增,这既能够保证唯一,使用起来又很方便,但int型的长度是有限的,如果超过长度怎么办呢? 暴露问题 我们先创建...
    99+
    2022-11-12
  • HTML行内级元素间的空格问题怎么解决
    这篇文章主要讲解了“HTML行内级元素间的空格问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“HTML行内级元素间的空格问题怎么解决”吧! 1....
    99+
    2022-10-19
  • vue-cli空格报错问题的分析及解决办法
    作为前端开发者,我们经常会使用到 Vue.js 框架,而在 Vue.js 开始学习阶段,我们更多时候会借助 vue-cli 工具来快速构建和管理项目,然而 vue-cli 工具在使用过程中,我们也可能会遇到一些问题。本篇文章就来跟大家分享一...
    99+
    2023-05-14
  • 如何解决电脑键盘空格键坏了的问题
    这篇文章给大家分享的是有关如何解决电脑键盘空格键坏了的问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。空格键失灵怎么办?空格键失灵一般不是电路问题,而是键帽下的金属条没有卡到正确的位置导致的,我们只要拆下空格键...
    99+
    2023-06-28
  • 解决mysql不是内部命令错误的问题
    解决mysql不是内部命令错误的问题?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!出现mysql不是内部命令的错误是因为没...
    99+
    2022-10-18
  • Docker部署mysql远程连接 解决2003的问题
    连接MySQL 这里我使用navicat远程连接,连接MySQL前需要防火墙开放端口或者关闭防火墙。 开放端口 firewall-cmd --add-port=3306/tcp ...
    99+
    2022-11-11
  • numpy强制类型转换的问题怎么解决
    本篇内容主要讲解“numpy强制类型转换的问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“numpy强制类型转换的问题怎么解决”吧!numpy强制类型转换今天用numpy遇到一个关于类...
    99+
    2023-06-30
  • 解决numpy和torch数据类型转化的问题
    在实际计算过程中,float类型使用最多,因此这里重点介绍numpy和torch数据float类型转化遇到的问题,其他类型同理。 numpy数据类型转化 numpy使用astype转...
    99+
    2022-11-12
  • Dreamweaver中不能输入多个空格的问题怎么解决
    这篇文章主要讲解了“Dreamweaver中不能输入多个空格的问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Dreamweaver中不能输入多个空格的问题怎么解决”吧!在Drea...
    99+
    2023-06-08
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作