开心一刻

  今天答应准时回家和老婆一起吃晚饭,但临时有事加了会班,回家晚了点

  回到家,本以为老婆会很生气,但老婆却立即从厨房端出了热着的饭菜

  老婆:还没吃饭吧,去洗下,来吃饭吧

  我洗好,坐下吃饭,内心感动十分;老婆坐旁边深情的看着我

  老婆:你知道谁最爱你吗

  我毫不犹豫道:你

  老婆:谁最关心你?

  我:你

  老婆:我是谁呀?

  我:我老婆

  老婆:那你以后是不是得对我好点?

  这时电话响了,一看好哥们打过来的,我接了并开了免提

  哥们:楼下洗浴八折,干啥呢?

  我:那个......,在陪我前妻吃口饭

问题背景

  一天,小伙伴找到我,他说他碰到一个很奇怪的问题

  他说:明明表名的入参是 test  ,为什么展示到界面的记录包括 test 这条记录?

  他补充道:会不会是 MyBatis-Plus 做了什么骚操作,把 test  末尾的空格给拿掉了

  我:你直接把 SQL 语句到 MySQL 执行下试试

  结果如下:

  这看起来不够直观,我移动下光标

  然后我和小伙伴面面相觑

环境准备

   MySQL5 、 MySQL8 各准备一个

  我们来看下默认情况下,末尾空白的判断情况

   MySQL 5.7.36 如下

  1 表示 TRUE ,也就是相等

   MySQL 8.0.27 如下

  0 表示 FALSE ,表示不相等

  这是什么原因,我们继续往下看

字符集与字符序

  比较肯定就需要比较规则, SQL 的比较规则就离不开字符序,字符序又与字符集相关,所以我们一个一个来捋

  字符集

  关于字符集,不是只言片语可以说清楚的,但是大家也不用担心,网上相关资料已经非常多,大家擦亮慧眼去查阅即可

  简单点来说:字符集定义了字符和字符的编码

  有人又问了:字符、字符的编码又是什么?

  为了方便大家理解,举个简单栗子

    有四个字符:A、B、C、D,这四个字符的编码分别是 A = 0, B = 1, C = 2, D = 3

    这里的字符(A、B、C、D) + 编码(0、1、2、3)就构成了字符集(character set)

   MySQL 支持的字符集有很多,可以通过 SHOW CHARACTER SET; 查看

   Charset :字符集名

   Description :描述

   Default collation :默认字符序

   Maxlen :每个字符最多字节数

  字符序

  定义了字符的比较规则;字符间的比较按何种规则进行

  一个字符集对应多个字符序,通过 SHOW COLLATION; 可以查看全部的字符序;也可以带条件查具体某个字符集的字符序

   Default 等于 Yes 表示是默认字符序

  每个字符集都有默认的字符序

  server的字符集与字符序

  当我们创建数据库时,没有指定字符集、字符序,那么server字符集、server字符序就会作为该数据库的字符集、字符序

  database的字符集与字符序

  指定数据库级别的字符集、字符序

  同一个MySQL服务下的数据库,可以分别指定不同的字符集、字符序

  创建、修改数据库的时候,可以通过 CHARACTER SET 、  COLLATE  指定数据库的字符集、字符序

  可以通过

  查看数据库的字符集和字符序

  table的字符集与字符序

  创建、修改表的时候,可以通过 CHARACTER SET 、 COLLATE 指定表的字符集、字符序

  可以通过

  查看表的字符序

  column的字符集与字符序

  类型为 CHAR 、 VARCHAR 、 TEXT 的列,可以指定字符集、字符序

  可以通过

  查看字段的字符集和字符序

  多个维度指定字符集、字符序的话,粒度越细的优先级越高( column > table > database > server )

  如果细粒度未指定字符集、字符序,那么会继承上一级的字符集,字符序则是上一级字符集的默认字符序

  通常情况下我们一般不会指定 table 、 column 粒度的字符集、字符序

  也就是说,通常情况下 column 的字符集会与 database 的字符集一致,而 column 的字符序则是 database 字符集的默认字符序

空白丢失

  上面讲了那么多,跟空白丢失有什么关系?

  大家先莫急,继续往下看

   MySQL5.7 The CHAR and VARCHAR Types中有这么一段

  翻译过来就是:

    1、类型是 CHAR 、 VARCHAR 、 TEXT 列的值,会根据列的字符序来比较和排序

    2、所有 MySQL 排序规则的类型都是 PAD SPACE 。这就意味着, CHAR 、 VARCHAR 、 TEXT 类型的值进行比较时,不用考虑任何末尾空格,LIKE 除外

    3、不受 SQL mode 影响,也就是说不管是严格模式,还是非严格模式,都不影响 2 所说的规则

  划重点,记笔记:在 MySQL5.7 及以下( <=5.7 )版本中,排序规则都是 PAD SPACE ,末尾的空格会忽略不考虑

  那如何让末尾空格参与比较了,有三种处理方式

  1、 BINARY ,类似 SELECT 'test' = BINARY 'test ';

  2、 LIKE ,类似 SELECT 'test' LIKE 'test ';

  3、 LENGTH 函数,类似

   MySQL8 做了调整,The CHAR and VARCHAR Types 有如下说明

  翻译过来就是:

    1、类型是 CHAR 、 VARCHAR 、 TEXT 列的值,会根据列的字符序来比较和排序

    2、 MySQL 字符序的 pad 参数的可选值,除了 PAD SPACE ,还增加了 NO PAD

    3、对于非二进制字符串( CHAR 、 VARCHAR 、 TEXT ),字符序 pad 参数决定如何去处理字符串末尾的空格

       NO PAD 不会忽略末尾空格,会将其当做其他字符一样对待

       PAD SPACE 会忽略末尾空格, LIKE 除外

       SQL mode 不参与字符串末尾空格的处理

   MySQL8 server 维度的字符集是 utf8mb4 ,对应的默认字符序是: utf8mb4_0900_ai_ci

   Pad_attribute 的值是 NO PAD ,也就是不会忽略字符串末尾的空格

  所以在 MySQL8 中, SELECT 'test' = 'test '; 默认情况下得到的结果是 0

总结

  1、非二进制字符串( CHAR 、 VARCHAR 、 TEXT )比较时,末尾空格的处理跟列的字符序有直接关系

  2、 MySQL5.7 及之前的版本,排序规则的类型都是 PAD SPACE ,会忽略字符串末尾的空格, LIKE 除外

  3、 MySQL8 开始,字符序增加了一个参数 Pad_attribute ,该参数的值不同,对字符串末尾空格的处理方式不同

     NO PAD :字符串末尾的空格会和其他字符一样,不会被忽略

     PAD SPACE :字符串末尾的空格会被忽略, LIKE 除外

  4、如上针对的都是非二进制字符串的排序和比较,而不是储存

参考

  The CHAR and VARCHAR Types

  The CHAR and VARCHAR Types

  再见乱码:5分钟读懂MySQL字符集设置

记一次字符串末尾空白丢失的排查 → MySQL 是会玩的!的更多相关文章

  1. 【Python】删除字符串的空白

    在程序中,额外的空白可能让人迷惑,对于程序员来说,'python'跟'python '看起来几乎一样,但是对于程序来说,可是千差万别 (lstrip)删除开头空白 >>> Langu ...

  2. mysql 字符串转数据丢失精度,mysql转换丢失精度,mysql CAST 丢失精度

    mysql 字符串转数据丢失精度,mysql转换丢失精度,mysql CAST 丢失精度 =============================== ©Copyright 蕃薯耀 2017年9月1 ...

  3. sql server2005版本中,len函数计算了字符串末尾的空格

    sql server2005版本中,len函数计算了字符串末尾的空格的长度,以下是测试脚本: print @@version declare @v varchar(max) set @v = 'hp, ...

  4. 解Bug之路-记一次中间件导致的慢SQL排查过程

    解Bug之路-记一次中间件导致的慢SQL排查过程 前言 最近发现线上出现一个奇葩的问题,这问题让笔者定位了好长时间,期间排查问题的过程还是挺有意思的,正好博客也好久不更新了,就以此为素材写出了本篇文章 ...

  5. Oracle数据库丢失表排查思路

    Oracle数据库丢失表排查思路 说明:由于系统采用ID取模分表法进行Oracle数据存储,某日发现Oracle数据库中缺少对应的几张业务数据表,遂进行相关问题查询,简单记录一下排查思路: 由于我们代 ...

  6. (转载)用PHP正则表达式清除字符串的空白

    (转载)http://www.chinaz.com/program/2009/0220/67569.shtml 我们经常会处理来自用户输入或从数据库中读取的数据,可能在你的字符串中有多余的空白或制表符 ...

  7. python 去除字符串末尾的子串

    建议使用 "字符串".replace("要去除的字符串", "") 尽量不要使用 strip() ,有时会引入意想不到的结果.strip() ...

  8. mysql 字符串数值计算 精度丢失

    我进行了一些测试.truncate(abs('414')/100,2)truncate('414'/100,2)truncate('4.14',2)truncate('4.1400',2)都有精度丢失 ...

  9. C字符串末尾的'\0'问题

    C语言的字符串要注意最后一位默认是'/0'的问题.这是一个易错点. strlen()计算长度时不考虑末尾的'\0' //例1 void test1() { ]; "; strcpy( str ...

  10. 汇编字符串末尾以00H或 0AH和00H结尾

    例如:db 'hello',0 用 C 语言百定义字符串时,编译软件会自动在字符串的末尾,加上一个零('\0').作为度字符串结束的标记. 用汇编的 DB 伪指令定义字符串,编译软件没有自动加上零的功 ...

随机推荐

  1. JsonCpp JSON格式处理库的介绍和使用(面向业务编程-文件格式处理)

    JsonCpp JSON格式处理库的介绍和使用(面向业务编程-文件格式处理) 介绍 JSON是一种轻量级的数据交换格式,它是一种键值对的集合.它的值可以是数字.字符串.布尔值.序列. 想知道更多有关J ...

  2. 投资组合计算分析——R语言

    "投资组合"是指金融资产(如股票.债券和现金)的任何组合.投资组合有很多类型,包括市场投资组合和零投资投资组合.可以使用以下任何一种投资方法和原则来管理投资组合的资产分配:股息加权 ...

  3. 游戏模拟——Position based dynamics

    目录 Verlet积分 基本积分方法 Verlet 算位置 Verlet 算速度 PBD 基于力的方法解碰撞 过冲问题 基于位置的方法解碰撞 算法流程 求解器借用的思想 关于动量守恒 约束投影 简单约 ...

  4. AtCoder Beginner Contest 236 E - Average and Median

    给定一个序列,要求相邻两个数至少选一个,求选出数的最大平均数和最大中位数 \(\text{sol}\):二分答案. 二分平均数\(\text{mid}\),将每个元素减去\(\text{mid}\), ...

  5. BPM工作流中的一些业务场景

    会签 会签是指两个或多个节点同时审批完,才能到下一节点. 案例: 合同流程 1.媒体合同需要CS.财务两部门共同审批确认:2.两个部门无审批顺序之分:3.需要两个部门全部审批通过后,流程才能往下走. ...

  6. SkyWalking的学习之一

    SkyWalking的学习之一 前言 最近在学习应用调优诊断等内容. 现在实际工作中实质上的拆分和微服务在售前阶段 所以真正用到链路的地方比较少. 但是人生都是要向前看的. 想着一方面提高自己. 一方 ...

  7. DeFi-W3

    Gas Fee 每一笔交易都会产生Gas Fee. GWei ETH的最小单位 出价(gas fee)的高低会影响交易上联的速度,越快就价格越高. gas fee是跟具体的计算量有关的 Smart c ...

  8. ping功能实现(ICMP)

    简单记录下项目中ping功能实现 笔记:ping功能实现 void Handler::handlePingDepot(const char *ip) { int mSize=50*1024; bzer ...

  9. 互异关系容斥&集合幂级数小记

    最近碰见了一些互异关系容斥的题目,而这类题目往往要配合集合幂级数的一些技术使用,所以简单记记. 内容很杂,行文很乱,作者水平很低,酌情观看. 互异关系容斥 思想其实很基本,应用范围其实很广. 原论文. ...

  10. 【Docker】镜像制作和管理

    一.Docker镜像说明 二.基于容器通过 docker commit 手动制作镜像 1.基于容器手动制作镜像步骤 1.下载官方系统镜像 2.基于官方基础镜像启动容器,并进入容器 3.在容器中进行配置 ...