数据库系列之MySQL数据库Varchar类型尾部空值问题

背景:研发人员在执行SQL语句“select xx from tb where c1=’aaa ’”查询时,发现并不能只查询出’aaa ’这样的字符串,而是把所有’aaa’这样的查出来。首先不管开发人员在插入数据的时候有没有进行去掉首尾字符串的处理,在MySQL 8.0版本中查询时会忽略掉字符串最后的空格,所以导致’aaa’+空格作为查询条件时和’aaa’为同一效果。为什么会出现这样的问题?


1、Char和Varchar的区别

MySQL数据库中char和varchar类型主要在存储方式和性能上有区别,主要有以下:

  • 存储方式:
    • CHAR:CHAR类型用于存储固定长度的字符序列。当你定义一个CHAR(M)字段时,MySQL会为该字段分配M个字符的空间,并使用空格来填充未达到长度的部分。例如,如果你有一个CHAR(10)字段并插入字串"Hello",MySQL会存储 "Hello "(注意尾部的空格)。
    • VARCHAR:VARCHAR类型用于存储可变长度的字符序列。当你定义一个VARCHAR(M)字段时,MySQL只会为该字段分配M个字符加上一个或两个额外字节的空间(用于存储字符串的长度)。如果字符串长度小于M,则只会使用必要的空间。例如,如果你有一个VARCHAR(10)字段并插入字符串"Hello",MySQL只会储"Hello"(没有额外的空格)。
  • 性能:
    • CHAR:由于CHAR字段的长度是固定的,所以在查询和比较时通常更快,因为MySQL可以直接定位到数据的位置,而无需先确定字符串的长度。但是,如果实际数据小于定义的长度,则会浪费存储空间。
    • VARCHAR:由于VARCHAR字段的长度是可变的,所以在查询和比较时可能需要一些额外的计算来确定字符串的长度。但是,VARCHAR可以更有效地利用存储空间,因为它只使用必要的空间。
  • 最大长度:
    • CHAR和VARCHAR的最大长度都受MySQL版本和字符集的影响。在大多数MySQL版本中,CHAR的最大长度是255个字符,而VARCHAR的最大长度是65,535个字节(这取决于实际使用的字符集,因为每个字符可能占用不同的字节数)。
  • 默认值:
    • 对于CHAR字段,如果没有明确指定默认值,MySQL会自动为其分配一个空格字符串作为默认值。
    • 对于VARCHAR字段,如果没有明确指定默认值,则其默认值为NULL。
  • 尾部空格:
    • 当从CHAR字段检索数据时,MySQL会删除尾部的空格(SQL Mode未配置PAD_CHAR_TO_FULL_LENGTH)。但是,在比较操作中,尾部的空格是会被考虑的。
    • VARCHAR字段在存储和检索时都保留实际的字符串内容,包括任何尾部的空格。

在官网上对于char和varchar解释如下:

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和varchar类型下存储大小:

在这里插入图片描述

2、Varchar对于尾部空格的处理

从上述得知,char类型查询时会忽略尾部空格,varchar其实也有类似的规则,从官网得知:

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。从官网得知两个属性的不同:

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:

  1. For PAD SPACE collations, trailing spaces are insignificant in comparisons; strings are compared without regard to trailing spaces.
  2. NO PAD collations treat trailing spaces as significant in comparisons, like any other character.

不同属性在查询时候表现也是不同的,如下所示:

mysql> SELECT COLLATION_NAME, PAD_ATTRIBUTE
       FROM INFORMATION_SCHEMA.COLLATIONS
       WHERE COLLATION_NAME LIKE 'utf8mb4%bin';
+------------------+---------------+
| COLLATION_NAME   | PAD_ATTRIBUTE |
+------------------+---------------+
| utf8mb4_bin      | PAD SPACE     |
| utf8mb4_0900_bin | NO PAD        |
+------------------+---------------+
mysql> SET NAMES utf8mb4 COLLATE utf8mb4_bin;
mysql> SELECT 'a ' = 'a';
+------------+
| 'a ' = 'a' |
+------------+
|          1 |
+------------+
mysql> SET NAMES utf8mb4 COLLATE utf8mb4_0900_bin;
mysql> SELECT 'a ' = 'a';
+------------+
| 'a ' = 'a' |
+------------+
|          0 |
+------------+

也就是说在UCA 9.0.0以后版本name_varchar的排序规则为NO PAD后,尾部空格参与比较,在这之前比较时忽略的尾部的空格。另外在mysql 8.x版本中,排序规则保存在information_schema库的COLLATIONS表中,可以通过以下语句查询对应的pad属性值。

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)
3、如何临时规避该问题

当字符集排序规则没法修改的情况下,如何规避CHAR和VARCHAR值进行比较都忽略尾部空格的问题,可以使用length函数的方法,如下所示:

select * from table where c1='xxx ' and length(c1) = length('xxx ');

参考资料:

  1. https://dev.mysql.com/doc/refman/8.0/en/char.html
  2. https://www.jb51.net/article/243476.htm

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

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

相关文章

基于RNN和Transformer的词级语言建模 代码分析 _generate_square_subsequent_mask

基于RNN和Transformer的词级语言建模 代码分析 _generate_square_subsequent_mask flyfish Word-level Language Modeling using RNN and Transformer word_language_model PyTorch 提供的 word_language_model 示例展示了如何使用循环神经网络RNN(GRU或LSTM)和 Transforme…

开源大模型框架概览3.1 TensorFlow与Keras3.1.1 TensorFlow简介

1.背景介绍 3.1 TensorFlow与Keras TensorFlow是Google Brain team在2015年发布的一个开源库,支持large-scale machine learning and deep neural networks。Keras是Python neural network library,它最初是由Franois Chollet开发的,并于20…

传统IT运维方式在数字化转型和业务扩展背景下面临哪些挑战?

近年来,IT部门的运维人员面对不断涌现的新兴技术和架构转型的要求,如企业上云中台互联网、分布式、容器化、双中心双活,大数据、人工智能的应用等等。随着传统企业把更多的业务向数字化转型,传统的IT运维方式在数字化转型和业务扩…

小程序抓包详细教程

小程序抓包详细教程 前言:关于小程序抓包一直想写出一个比较详细的教程 实验设备: ​ 微信: https://windows.weixin.qq.com/?langzh_CN ​ Proxifier:https://www.proxifier.com/download/ (需要挂梯子访问下载) ​ burpsuite&#xff…

电源滤波器怎么选怎么用1

电源滤波器怎么选怎么用 第一步第二步第三步第四步 很多人不懂得选型,都是买一大堆在现场直接挨个挨个测试,哪一个是通过了就算哪一个。是的我也是这样子搞得。那如何选择最优、最经济、最实用、最有效的滤波器呢?选择电源滤波器的过程有这么…

BioPorto胰高血糖素样肽-1抗体(GLP-1)

丹麦BioPorto Diadnostics公司致力于提供世界领先的GLP-1抗体。基于结合GLP-1位点的不同,他们筛选出了不同的抗GLP-1抗体。有的抗体可以同时结合GLP-1的活性形式和非活性形式,有的专门结合生物活性形式的GLP-1。在开发和检测GLP-1相关治疗的过程中&#…

初探Flask:Pycharm社区版创建Flask项目

文章目录 一、创建工程二、引入Flask库1.使用命令行安装Flask2.在PyCharm中安装Flask 三、创建Flask框架基本文件四、运行项目 本文将带您一步步创建一个简单的Flask项目,包括设置Python环境、安装Flask库以及创建基本的项目结构。 一、创建工程 首先,确…

Kibana的使用

在学习elasticsearch时,可以使用Kibana自带的开发工具,来提高效率, 浏览器打开Kibana,在左侧菜单栏中找到Dev Tools 该工具提供代码提示和代码格式化功能,非常有用,

SSMP整合案例第七步 前后端业务异常消息统一处理

异常消息处理 我们当前的增删改查基本完成 我们当前的情况是在理想状态下完成的 但是实际开发中我们要抛出异常 业务在进行处理的时候 数据格式就是这样 前端拿到的信息我们应该去处理 前端如何去处理得去斟酌 即使前端出现了异常 我们也要让返回的异常信息让前端成功读…

SpringBoot——整合Servlet的三大组件:监听器(Listener)

目录 监听器(Listener) 项目总结 MyRequestListener自定义监听器 WelcomController控制器 SpringbootListenerApplication启动类 在开发SpringBoot项目时,开发人员经常需要对HTTP请求进行拦截和处理,以实现诸如身份验证、授…

室内外无缝定位技术:连接虚拟与现实的新桥梁

随着科技的快速发展,人们对于位置信息的精确度和实时性要求日益提高。在这样一个背景下,室内外无缝定位技术应运而生,成为连接虚拟与现实世界的关键桥梁。它不仅为人们提供了更加便捷、高效的生活体验,还推动了物联网、智能制造等…

家用厨房安全新篇章:煤气安全阀结构与校验知识普及

在家用厨房中,煤气作为主要的烹饪能源,其安全性至关重要。 煤气安全阀作为防止煤气泄露的关键设备,其结构特点、作用解析、定期校验的重要性以及泄露风险的防范等方面,都是我们必须深入了解和掌握的知识。 首先,我们…

Java1.8 vue版家政服务系统成品源码 家政管家系统源码 家政月嫂系统源码 家政保洁系统源码 在线派单,师傅入驻全套商业源码

Java1.8 vue版家政服务系统成品源码 家政管家系统源码 家政月嫂系统源码 家政保洁系统源码 在线派单,师傅入驻全套商业源码 一、系统定义 家政上门服务系统是一种利用互联网技术,将家政服务需求与专业的家政服务人员进行高效匹配的平台。它允许用户通过…

leetcode第263题:丑数

丑数的因子只能是2,3,5。但是可能有多个2&#xff0c;多个3&#xff0c;多个5.因此需要循环地除以2、3、5. public class Solution {public bool IsUgly(int n) {if (n < 0) {return false;}int[] factors {2, 3, 5};for ( int i0;i<3;i) {int factorfactors[i];while …

ClickHouse如何整合数据源:MySQL、HDFS...

一、ClickHouse数据源 ClickHouse 作为一个强大的列式数据库管理系统&#xff0c;支持多种数据源&#xff0c;使得用户能够方便地将数据导入 ClickHouse 进行存储和分析。以下是常见的 ClickHouse 数据源&#xff1a; 外部数据源 HDFS&#xff1a; 支持从 Hadoop 分布式文件系…

音视频开发15 FFmpeg FLV封装格式分析

FLV(Flash Video)简介 FLV(Flash Video)是Adobe公司推出的⼀种流媒体格式&#xff0c;由于其封装后的⾳视频⽂件体积⼩、封装简单等特点&#xff0c;⾮常适合于互联⽹上使⽤。⽬前主流的视频⽹站基本都⽀持FLV。采⽤ FLV格式封装的⽂件后缀为.flv。 FLV封装格式的组成 FLV封装…

长三角Ai行业盛会:2024南京人工智能展会(南京智博会)

在长三角地区&#xff0c;南京这座古老而现代的都市&#xff0c;近年来在人工智能产业发展方面取得了令人瞩目的成绩。作为一座拥有深厚历史底蕴和独特文化魅力的城市&#xff0c;南京在科技创新领域同样展现出非凡的活力与实力。特别是在人工智能领域&#xff0c;南京的崛起已…

Spring Cloud:构建高可用分布式系统的利器

摘要&#xff1a;本文将介绍Spring Cloud&#xff0c;一个基于Spring Boot的开源微服务架构工具集。我们将探讨Spring Cloud的核心组件、特性以及如何使用Spring Cloud构建高可用、分布式系统。通过本文&#xff0c;读者将了解到Spring Cloud在实现微服务架构中的应用和优势。 …

STM8单片机变频器设计

变频调速技术是现代电力传动技术的重要发展方向,而作为变频调速系统的核心—变频器的性能也越来越成为调速性能优劣的决定因素,除了变频器本身制造工艺的“先天”条件外,对变频器采用什么样的控制方式也是非常重要的。随着电力电子技术、微电子技术、计算机网络等高新技术的…

React-生成随机数和日期格式化

生成随机数 uuid文档&#xff1a;https://github.com/uuidjs/uuid npm install uuid import {v4 as uuidV4} from uuid 使用&#xff1a; uuidV4() 日期格式化 dayjs文档&#xff1a;安装 | Day.js中文网 npm install dayjs import dayjs from dayjs