Skip to main content

Command Palette

Search for a command to run...

想当然之MySQL的字符串大小写敏感

Published
2 min read

通常情况,想当然代表对知识理解不够,修行不够深,当我意识到自己是想当然的时候, 非常汗颜,但同是也了新的知识。无知并不可怕,可怕的是无知还不自知。

先描述理解,我司与某银行进行对接充值数据,主要是将用户在银行的充值记录(当天的转账流水号唯一), 同步到我司自己的数据库中,某天查询银行网关的数据条目为140条,但是同步任务同步到我司自己的数据库中只有138条, 少了两条,感觉很奇怪,查到这两条未同步数据有一个特点:这两条转账流水号若不区分大小写的话,已经存在于我司的数据库中, 我第一反应是:怎么可能,难道mysql的varchar类型大小写不敏感? 话不多说,这个一试便知

先看一下我本地的数据库版本

MariaDB [examples]> select @@version;
+---------------------+
| @@version           |
+---------------------+
| 10.3.10-MariaDB-log |
+---------------------+
1 row in set (0.000 sec)

表结构如下

CREATE TABLE `assume` (
  `id` bigint(64) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(12) NOT NULL,
  `trans_no` varchar(12) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name_no_idx` (`name`,`trans_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

我们试着插入一条数据

MariaDB [examples]> insert into assume (name, trans_no) values("sql", "asdf");
Query OK, 1 row affected (0.037 sec)

ok, 数据插入成功,还是用上一条插入的数据, 只不过这次name字段首字段我们改成大写

MariaDB [examples]> insert into assume (name, trans_no) values("sql", "Asdf");
ERROR 1062 (23000): Duplicate entry 'sql-Asdf' for key 'name_no_idx'
MariaDB [examples]>

真的假的,sql-asdfsql-Asdf明明就不一样啊,怎么会这样? 但是从报错来看,mysql又似乎认为sql-asdfsql-Asdf是重复记录? 工作四年,印象中是第一次遇到这种情况,这就是之前的想当然。 赶紧查一下mysql文档

For nonbinary strings (CHAR, VARCHAR, TEXT), string searches use the collation of the comparison operands. For binary strings (BINARY, VARBINARY, BLOB), comparisons use the numeric values of the bytes in the operands; this means that for alphabetic characters, comparisons will be case-sensitive.

秀一下我拙劣的翻译:

对于非二进制字符串(CHARVARCHARTEXT),字符串搜索使用比较操作数的排序。对于二进制字符串(BINARY、VARBINARY、BLOB),比较使用操作数中字节的数值;这意味着对于字母字符,比较是区分大小写的(?这句表示没看懂)。

非二进制字符串和二进制字符串之间的比较被视为二进制字符串之间的比较。

简单的比较操作(>=、>、=、<、<=、排序和分组)基于每个字符的“排序值”。具有相同排序值的字符将被视为相同字符。例如,如果eé在给定的排序规则中具有相同的排序值,那么它们的比较就相等。

默认的字符集和排序规则是utf8mb4utf8mb4_0900_ai_ci,因此默认情况下,非二进制字符串比较不区分大小写

查看一下当前的COLLATION(排序规则)版本

MariaDB [examples]> SELECT COLLATION(VERSION());
+----------------------+
| COLLATION(VERSION()) |
+----------------------+
| utf8_general_ci      |
+----------------------+

也就是说在utf8_general_ci的字符规则中,是不区分大小写的

MariaDB [examples]> select 'a' ='A';
+----------+
| 'a' ='A' |
+----------+
|        1 |
+----------+
1 row in set (0.024 sec)

MariaDB [examples]> select 'a' ='b';
+----------+
| 'a' ='b' |
+----------+
|        0 |
+----------+

回到assume这张表,我的本意是nametrans_no是需要区分大小写的,可以修改字符排序规则属性为二进制类型

alter table `assume` MODIFY column name varchar(12) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;
alter table `assume` MODIFY column trans_no varchar(12) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;

此时便能

MariaDB [examples]> show create table assume \G;
*************************** 1. row ***************************
       Table: assume
Create Table: CREATE TABLE `assume` (
  `id` bigint(64) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(12) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `trans_no` varchar(12) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name_no_idx` (`name`,`trans_no`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
1 row in set (0.001 sec)

ERROR: No query specified

MariaDB [examples]> insert into assume (name, trans_no) values("sql", "Asdf");
Query OK, 1 row affected (0.010 sec)

我感觉这样设计很奇怪,不明白为何如此设计,按之前的想当然, 应该默认大小写敏感才是,google搜索无果,诸公若有线索,欢迎留言,不胜感激。

参考:

  • mysql case sensitivity
  • https://stackoverflow.com/questions/6448825/sql-unique-varchar-case-sensitivity-question
27 views

More from this blog

2025: 祛魅 灰度 念头通达

今天是2025年的最后一天,当大家都在准备下班的时候,好巧不巧的,我刚好发现了一个不大不小的问题,大胆猜想,小心求证,向上反馈,暴露风险,作为2025年工作注解,实在是再有趣不过了。 今年的工作,从结果上看,还算平稳,至于过程,有太多不可言说的部分。厂里打镙丝的牛马,有工资可拿,理应知足了,至于其它的,与己无关,也没那么重要了。 祛魅 近距离观察大厂,才发现一些违背常识/直觉的事实:路人以为的高大

Feb 28, 20261 min read21

大厂祛魅:破碎的专注力

毁掉一个人最直接的方法,就是毁掉ta的专注力。 这句话的出处已然模糊,但放在大厂环境中,却显得格外深刻。 围城 大厂宛如一座围城。城外的人满怀憧憬,目之所及皆是光鲜;城内的人却如困笼之鸟,翅膀日渐退化,每日挣扎求生。 高大上 不可否认,大厂的硬件设施确实令人艳羡:宽敞的独立园区内,来往穿梭的人群中,几乎人人手握智能设备。这看似现代化的景象背后,却藏着一个无奈的事实:在工作时段,每台电脑都被严密监控,连听音乐都成奢望。于是,工作之余玩手机,成了许多人难得的解压方式。 大厂的品牌效应确实强大。外界对...

Jul 29, 20251 min read138

Black Swan

黑天鹅理论 是指极不可能发生,实际上却又发生的事件 来到大厂打工已经满一个月了,从一开始的手足无措,到逐渐度过不适期,也算是适应了吧。 不适应 刚入职时,不适应的地方还是挺多的。 第一次只使用台式机工作,这就限制了我一天中的绝大部分时间,都必须呆在自己的工位上,好在工位足够大。只是人与人的沟通少了很多,有问题只能在工位上通过 IM 呼对方,有种魔幻又现实的感觉 第一次只能用 Windows,也不能 WSL,这给我的工作效率带来了很大影响,不能用熟悉的软件,就连写代码用的 VSCode 的...

Jan 24, 20251 min read74

2024年: 逐渐平静

这个世界是一面镜子,会把你的感受反射给你 2024 开端: 相由心生 那时,还带着一着愤懑,因为拿到了低绩效,虽然内心知道这是公司经营困难,想让我离开的一种策略,但仍然感受到自己那可笑的自尊受到了践踏。自那之后,非必要不加班,只做份内事,尽可能地不去涉及份外之事。 2024 年中: 与人为善 组里的项目眼见不行了,我被迫去支援 AI 项目,久违地写起了 python,项目接近完成时,意外收到通知:我拿到大礼包了。在这之前,架构师因故裸辞。在我离开之后不到两周,我的 TL 也裸辞了,直到同事告诉...

Jan 9, 20251 min read92

企业软件之殇

殇 动词 未成年而死。 名词 战死者。 笔者经历了两家打着云原生旗号的企业软件/解决方案公司,都是中途加入,项目都以解(失)散(败)告终。 云原生解决方案 NB 公司:一个传统的 IDC 小厂,想着借云原生的热度,进军企业软件市场。 在加入这个项目之前,笔者考取了 CKAD 认证,彼时对 K8s 相当着迷。先简要介绍一下这个项目背景: 基于 Rancher (换皮肤)的二次开发项目,名字叫:HCaaS ,在笔者加入这个团队之前,项目已经开发近两年了,除了 TL 之外,其它人之前都...

Jul 1, 20241 min read103

just for fun

57 posts

I'm a Software Engineer