MySQL中的字符集与排序规则

作者:程序新视界日期:2025/11/20

在MySQL中,当使用字符串类型时,有两方面的知识我们需要特别关注一下:字符集和排序规则。如果使用不当,则可能会导致性能问题或在插入数据时出现一些异常情况。

字符集定义了对应列允许使用的字符,而排序规则是用于比较这些字符的基础规则。通常,每个类型的字符集都会有多种排序规则,但一个排序规则只能属于一个字符集。

这篇文章,我们就围绕MySQL中字符集以及排序规则展开,详细聊聊相关的技术点。

MySQL中的字符集

MySQL支持广泛的字符集,包括GB2312、GBK、BIG5等本地字符集,以及多种Unicode字符集,如utf8mb3 (MySQL中旧版的utf8)、utf8mb4ucs2utf16utf32utf8mb4是推荐使用的字符集,因为它能完整支持所有Unicode字符,包括表情符号和不常用的汉字。

可以使用下面的命令在information_schema数据库中查看所有字符集:

1mysql> SELECT * FROM information_schema.character_sets ORDER BY character_set_name;
2+--------------------+----------------------+---------------------------------+--------+
3| CHARACTER_SET_NAME | DEFAULT_COLLATE_NAME | DESCRIPTION                     | MAXLEN |
4+--------------------+----------------------+---------------------------------+--------+
5| armscii8           | armscii8_general_ci  | ARMSCII-8 Armenian              |      1 |
6| ascii              | ascii_general_ci     | US ASCII                        |      1 |
7| big5               | big5_chinese_ci      | Big5 Traditional Chinese        |      2 |
8| binary             | binary               | Binary pseudo charset           |      1 |
9……
10……
11……
12| utf16              | utf16_general_ci     | UTF-16 Unicode                  |      4 |
13| utf16le            | utf16le_general_ci   | UTF-16LE Unicode                |      4 |
14| utf32              | utf32_general_ci     | UTF-32 Unicode                  |      4 |
15| utf8               | utf8_general_ci      | UTF-8 Unicode                   |      3 |
16| utf8mb4            | utf8mb4_0900_ai_ci   | UTF-8 Unicode                   |      4 |
17+--------------------+----------------------+---------------------------------+--------+
18

通过上述命令可以列出当前MySQL支持的所有字符集,以及它们的默认排序规则。每种字符集都有一个默认排序规则。

在上述命令展示的列表底部,有两个字符集被描述为UTF-8 Unicode。utf8字符集的MAXLEN为3,而utf8mb4MAXLEN为4。这里指的是每个字符允许的最大字节长度。

特别需要留意的是,根据UTF-8标准,每个字符允许使用最多4个字节,这意味着MySQL的utf8字符集实际上并不是真正的UTF-8,因为它只支持每字符最多3个字节。从MySQL 8开始,utf8mb4成为默认字符集,也是最常使用的字符集。utf8被保留用于向下兼容,应该不再使用。

如何定义字符集

定义列的字符集有几种方式。如果你没有在表或列级别指定字符集,服务器默认的utf8mb4字符集将被应用(除非你明确声明了一个不同的服务器或数据库默认设置)。

我们可以通过创建一个没有字符集信息的表并读取其定义来验证这一点:

1CREATE TABLE no_charset (
2  my_column VARCHAR(255)
3);
4
5SHOW CREATE TABLE no_charset;
6

生成的CREATE TABLE语句显示了默认的字符集和排序规则已经被应用:

1CREATE TABLE `no_charset` (
2  `my_column` varchar(255) DEFAULT NULL
3) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
4

在表级别定义

你可以显式地在表级别设置字符集,通过使用CHARSET=[字符集]语法。例如,这里我们创建一个所有字符列都使用latin1字符集的表:

1CREATE TABLE no_charset (
2  `my_column` VARCHAR(255) DEFAULT NULL
3) ENGINE=InnoDB DEFAULT CHARSET=latin1;
4

在列级别定义

你也可以在列级别设置字符集。这是最具体的设置,会覆盖任何表级别的设置:

1CREATE TABLE `mixed_collations` (
2  `explicitly_set` VARCHAR(255) CHARACTER SET latin1,
3  `implicitly_set` VARCHAR(255)
4);
5

通过运行SHOW CREATE TABLE mixed_collations可以看到表的默认字符集是utf8mb4,但是显式设置的列使用了latin1字符集:

1CREATE TABLE `mixed_collations` (
2  `explicitly_set` VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
3  `implicitly_set` VARCHAR(255) DEFAULT NULL
4) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
5

列级别的声明将覆盖表级别的声明,表级别的声明将覆盖数据库默认,数据库默认的字符集覆盖服务器默认。

MySQL中的排序规则

字符集定义了可以存储在列中的合法字符,而排序规则则是确定如何进行字符串比较的规则。如果你在排序或比较字符串,MySQL就会使用排序规则来决定顺序以及判断字符串是否相同。

可以通过查询information_schema表来显示所有排序规则。下面的查询仅显示与utf8mb4字符集相关的排序规则:

1mysql> SELECT
2    ->   *
3    -> FROM
4    ->   information_schema.collations
5    -> WHERE
6    ->   character_set_name = 'utf8mb4'
7    -> ORDER BY
8    ->   collation_name;
9+----------------------------+--------------------+-----+------------+-------------+---------+---------------+
10| COLLATION_NAME             | CHARACTER_SET_NAME | ID  | IS_DEFAULT | IS_COMPILED | SORTLEN | PAD_ATTRIBUTE |
11+----------------------------+--------------------+-----+------------+-------------+---------+---------------+
12| utf8mb4_0900_ai_ci         | utf8mb4            | 255 | Yes        | Yes         |       0 | NO PAD        |
13| utf8mb4_0900_as_ci         | utf8mb4            | 305 |            | Yes         |       0 | NO PAD        |
14| utf8mb4_0900_as_cs         | utf8mb4            | 278 |            | Yes         |       0 | NO PAD        |
15| utf8mb4_0900_bin           | utf8mb4            | 309 |            | Yes         |       1 | NO PAD        |
16| utf8mb4_bin                | utf8mb4            |  46 |            | Yes         |       1 | PAD SPACE     |
17……
18……
19……
20

该查询将显示所有排序规则、相关字符集名称、是否为默认值以及其他信息。例如,utf8mb4_0900_ai_ciutf8mb4字符集的默认排序规则。

排序规则的命名规则

排序规则的命名通常前缀为字符集名称,后缀由排序规则的属性组合而成。

以下是一些主要后缀及其含义:

后缀含义
_ai不区分重音符
_as区分重音符
_ci不区分大小写
_cs区分大小写
_ks区分假名
_bin二进制比较

例如,默认排序规则utf8mb4_0900_ai_ci可以拆解:

  • utf8mb4:属于utf8mb4字符集;
  • 0900:使用UCA 9.0.0的权重键;
  • _ai:不区分重音符;
  • _ci:不区分大小写。

那么,字符串比较是否区分大小写?答案是:“视具体排序规则而定!”

验证排序规则

我们可以使用COLLATE关键字显式设置字符串的排序规则:

1mysql> SELECT "MySQL" COLLATE utf8mb4_0900_ai_ci = "mysql" COLLATE utf8mb4_0900_ai_ci;
2+-------------------------------------------------------------------------+
3| "MySQL" COLLATE utf8mb4_0900_ai_ci = "mysql" COLLATE utf8mb4_0900_ai_ci |
4+-------------------------------------------------------------------------+
5|                                                                       1 |
6+-------------------------------------------------------------------------+
7

此查询返回结果值为1,表示MySQL认为这两个字符串相等。如果改用区分大小写的排序规则,我们会得到不同的结果:

1mysql> SELECT "MySQL" COLLATE utf8mb4_0900_as_cs = "mysql" COLLATE utf8mb4_0900_as_cs;
2+-------------------------------------------------------------------------+
3| "MySQL" COLLATE utf8mb4_0900_as_cs = "mysql" COLLATE utf8mb4_0900_as_cs |
4+-------------------------------------------------------------------------+
5|                                                                       0 |
6+-------------------------------------------------------------------------+
7

此查询返回结果值为0,表明MySQL认为这两个字符串不同,因为它们大小写不同。

类似逻辑也适用于重音符。例如,在使用不区分重音符的排序规则时,resumerésumé会被认为是相同的。

如何定义排序规则

与字符集类似,排序规则可以在表级别或列级别设置。如果未显式定义排序规则,MySQL会使用字符集的默认排序规则。

表级别定义

可以在CREATE TABLE语句中使用COLLATE子句定义表的排序规则。例如,以下创建了一个所有字符列都使用utf8mb4_bin排序规则的表:

1CREATE TABLE table_with_collation (
2  my_column VARCHAR(255)
3) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
4

列级别定义

也可以在列定义中设置排序规则。例如:

1CREATE TABLE table_with_collation (
2  `explicitly_set` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
3  `implicitly_set` varchar(255)
4) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
5

此外,也可以通过ALTER TABLE语句修改现有表列的排序规则:

1ALTER TABLE table_with_collation
2    CHANGE `explicitly_set` `explicitly_set` varchar(255)
3        CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
4

小结

理解字符集和排序规则是处理MySQL字符串数据的基础。字符集定义了列中存储的合法字符,排序规则决定了字符串比较的方式。

  • 字符集可以在列级别、表级别定义,或者继承自数据库或服务器默认值。最具体的层级(列 > 表 > 数据库 > 服务器)将会被采用。
  • 排序规则可以在列级别、表级别定义,或者继承自字符集默认。仍然是最具体的层级优先。

列的字符集和排序规则会影响数据存储方式以及数据的比较和排序行为。在设计数据库时需注意这些设置,以确保行为正确并优化性能。

如果不确定应使用哪个字符集或排序规则,MySQL默认的utf8mb4字符集及其默认排序规则utf8mb4_0900_ai_ci通常是一个不错的选择。它们支持所有Unicode字符并提供大小写不敏感和重音符不敏感的比较功能。


MySQL中的字符集与排序规则》 是转载文章,点击查看原文


相关推荐


基于 Kafka 与时间轮实现高性能延迟消息
master_hl2025/11/19

1.整体链路 Kafka → RocksDB → SystemTimer → TimingWheel → Kafka public void sendDelay(long delayMs, String topic, String message) { try { DelayMessage delayMessage = new DelayMessage(delayMs, topic, message); rocksDB.put(delayMessage.g


Python 的内置函数 sum
IMPYLH2025/11/17

Python 内建函数列表 > Python 的内置函数 sum Python 的内置函数 sum() 是一个用于计算可迭代对象中所有元素之和的高效工具。这个函数可以接受一个可迭代对象(如列表、元组、集合等)作为参数,并返回其中所有元素的总和。 基本用法 numbers = [1, 2, 3, 4, 5] total = sum(numbers) # 返回 15 可选参数 sum() 函数还接受一个可选的第二个参数 start,用于指定求和的初始值。默认情况下 start 为 0。


ios包体积管理方案
denggun123452025/11/16

iOS 包体积优化是一个系统性的工程,需要从代码、资源、第三方库、构建配置等多个维度进行综合管理。下面我将梳理一个全面的 iOS 包体积管理方案。 一、包体积分析 在进行任何优化之前,必须先了解 App 体积到底由什么构成。 使用 Xcode 的 App Thinning Size Report 操作:Archive -> Distribute App -> App Store Connect -> 选择 Ad Hoc 或 App Store -> Next -> 在 "App T


Bash 入门
hubenchang05152025/11/15

#Bash 入门 #Hello World Bash 的内置命令 echo 可以打印文本。例如: $ echo Hello World Hello World echo 命令的 -e 选项激活转义字符的解释。例如: $ echo -e "Hello \n World" Hello World #命令格式 Bash 命令基本遵循以下格式: 命令 参数1 参数2 参数3 ... 例如在 echo Hello World 中,echo 是命令,Hello 是参数1,World 是参数2。 而


Python 的内置函数 issubclass
IMPYLH2025/11/14

Python 内建函数列表 > Python 的内置函数 issubclass Python 的内置函数 issubclass 用于检查一个类是否是另一个类的子类(直接或间接继承)。它是 Python 面向对象编程中类型检查的重要工具。 语法 issubclass(class, classinfo) 参数说明 class:需要检查的类(必须是类对象,不能是实例)classinfo:可以是一个类对象,或者由类对象组成的元组 返回值 返回布尔值: True:如果 class 是 c


Flutter 3.38 发布,快来看看有什么更新吧
恋猫de小郭2025/11/13

在 11 月 13 日的 FlutterFlightPlans 直播中,Flutter 3.38 如期而至,本次版本主要涉及 Dot shorthands、Web 支持增强、性能改进、问题修复和控件预览等方面。 Dot shorthands 在 Dart 3.10 + Flutter 3.38 中开始默认支持 Dot shorthands ,通过 Dot shorthands 可以使用简写方式省略类型前缀,例如使用 .start 而不是 MainAxisAlignment.start : /


HTML 的 <canvas> 标签
hubenchang05152025/11/11

#HTML 的 <canvas> 标签 请查看 HTML 元素帮助手册 了解更多 HTML 元素。 <canvas> 元素可被用来通过 JavaScript(Canvas API 或 WebGL API)绘制图形及图形动画。 #属性 请查看 HTML 元素的全局属性 了解 HTML 元素的全局属性。 height: 该元素占用空间的高度,以 CSS 像素(px)表示,默认为 150。 moz-opaque(废弃): 通过设置这个属性,来控制 canvas 元素是否半透明。如果你不想 c


CCState:为大型 Web 应用设计的状态管理库
温宇飞2025/11/9

CCState 是一个基于 Signal 的状态管理库。它通过三种语义化的信号类型(State、Computed、Command)实现读写能力隔离,并原生支持 async/await 的异步计算,让状态管理变得简单直观。CCState 与框架无关,可与 React、Vue、Solid.js 等任何 UI 框架无缝集成。它在 秒多 等项目中得到验证,为大规模应用而设计。 快速上手 Signal Signal 是一个轻量级的描述对象,它本身不存储值,只是一个"引用"或"标识符"。所有 Signal


为什么你的JavaScript代码总是出bug?这5个隐藏陷阱太坑了!
良山有风来2025/11/7

你是不是经常遇到这样的情况:明明代码看起来没问题,一运行就各种报错?或者测试时好好的,上线后用户反馈bug不断?更气人的是,有时候改了一个小问题,结果引出了三个新问题…… 别担心,这绝对不是你的能力问题。经过多年的观察,我发现大多数JavaScript开发者都会掉进同样的陷阱里。今天我就来帮你揪出这些隐藏的bug制造机,让你的代码质量瞬间提升一个档次! 变量声明那些事儿 很多bug其实从变量声明的那一刻就开始埋下了隐患。看看这段代码,是不是很眼熟? // 反面教材:变量声明混乱 function


【基础算法】DFS中的剪枝与优化
让我们一起加油好吗2025/11/2

文章目录 上文链接一、剪枝与优化1. 排除等效冗余2. 可行性剪枝3. 最优性剪枝4. 优化搜索顺序5. 记忆化搜索 二、OJ 练习1. 数的划分(1) 解题思路(2) 代码实现 2. 小猫爬山(1) 解题思路(2) 代码实现 上文链接 【基础算法】DFS 一、剪枝与优化 剪枝,形象地看,就是剪掉搜索树的分支,从而减小搜索树的规模,排除掉搜索树中没有必要的分支,优化时间复杂度。 在深度优先遍历中,有几种常见的剪枝方法: 1. 排除等效冗余 如

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读