MySQL WEIGHT_STRING 怎样比较排序规则产生的权重
来源:17golang原创
时间:2026-10-29 15:42:59 492浏览 收藏
排查“为什么两个字符串在排序时看起来相等”时,直接把原文转成十六进制并不够,因为 MySQL 的字符比较会受字符集和排序规则影响。WEIGHT_STRING() 返回的不是原字符串,而是参与比较和排序的二进制权重;用 HEX() 包一层,就能把不可打印的二进制值变成便于对照的十六进制文本。
官方地址:https://dev.mysql.com/doc/refman/8.4/en/string-functions.html
最稳妥的看法是:先显式固定字符集与排序规则,再用HEX(WEIGHT_STRING(...))比较结果;如果输入本来就是BINARY,看到的则是字节值,不是字符排序权重。
先把排序权重变成可读结果
WEIGHT_STRING(str) 返回二进制字符串。对于 CHAR、VARCHAR、TEXT 等非二进制字符输入,它包含当前排序规则用于比较的权重;对于 BINARY、VARBINARY、BLOB 输入,它按字节值处理。调试时建议始终配合 HEX():
-- 用固定字符集和排序规则观察字符权重;HEX 只负责把二进制结果显示成可读文本
SET @s = _utf8mb4 'AB' COLLATE utf8mb4_0900_ai_ci;
SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
-- 预期观察形式:原文的 HEX 与权重的 HEX 是两列不同含义
-- @s = AB,HEX(@s) = 4142,权重 HEX 类似 1C471C60
这里的关键不是记住某一串十六进制数字,而是区分两层:HEX(@s) 是字符编码后的字节表现,HEX(WEIGHT_STRING(@s)) 才是排序规则参与比较的权重表现。官方手册把该函数定位为内部调试用途,因此不应把具体权重编码当作业务协议。
固定排序规则后,权重到底表示什么
排序规则改变时,同一段文本可能得到不同权重;同一排序规则也可能让大小写不同的文本得到相同权重。例如在大小写不敏感的排序规则下,AB 与 ab 的权重可以相同,这正是排序时被视为等价的原因之一:
-- 两个表达式显式使用同一排序规则,便于对照比较权重
SET @upper = _utf8mb4 'AB' COLLATE utf8mb4_0900_ai_ci;
SET @lower = _utf8mb4 'ab' COLLATE utf8mb4_0900_ai_ci;
SELECT
HEX(WEIGHT_STRING(@upper)) AS upper_weight,
HEX(WEIGHT_STRING(@lower)) AS lower_weight,
WEIGHT_STRING(@upper) = WEIGHT_STRING(@lower) AS same_weight;
-- 该结果用于解释排序规则;不要把权重字节直接保存为跨版本业务字段
按官方定义,如果两个权重相等,两个字符串在该比较语境下被视为相等;权重较小的字符串排在权重较大的字符串之前。注意,这个结论依赖输入携带的字符语义。只比较原始 UTF-8 字节,不能替代对排序规则的观察。

字符字符串和二进制字符串不要混着看
同样写成 AB,如果显式转换成二进制字符串,WEIGHT_STRING() 返回的就是输入字节本身。下面两组结果的差异,说明“字符排序权重”和“字节值”是两条不同的排查路线:
-- 字符串走排序规则权重;二进制字符串按每个字节的数值返回
SET @text_value = _utf8mb4 'AB' COLLATE utf8mb4_0900_ai_ci;
SET @binary_value = CAST('AB' AS BINARY);
SELECT HEX(WEIGHT_STRING(@text_value)) AS collation_weight;
SELECT HEX(WEIGHT_STRING(@binary_value)) AS byte_weight;
-- 字符输入的结果由排序规则决定;BINARY 输入通常与 4142 这类原始字节表示一致
因此,遇到排序结果与预期不同,先确认列是字符类型还是二进制类型,再确认表达式有没有显式 COLLATE。不要看到十六进制结果就直接断言“编码错了”。
AS CHAR 与 AS BINARY 怎样改变长度边界
AS 子句可以把输入强制成指定类型和长度。AS CHAR(N) 按字符计数,右侧用空格补齐;AS BINARY(N) 按字节计数,右侧用 0x00 补齐。若输入超过长度,都会截断且不会因为这个截断产生警告:
-- 对比字符长度和字节长度的补齐规则;N 的单位随类型变化
SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4))) AS char_weight;
SELECT HEX(WEIGHT_STRING('ab' AS BINARY(4))) AS binary_weight;
-- CHAR(4) 的示例会体现空格补齐;BINARY(4) 会体现 0x00 补齐
-- 过长输入按目标长度截断,示例只用于定位长度边界
SELECT HEX(WEIGHT_STRING('abcdef' AS CHAR(4))) AS truncated_char;
SELECT HEX(WEIGHT_STRING('abcdef' AS BINARY(4))) AS truncated_binary;
这个差异很适合解释固定宽度字段、导入比较或排序异常:字符类型的长度单位是字符,二进制类型的长度单位是字节。多字节字符场景下,不能把两者的 N 当成同一个尺度。

实际排查时记住这三个边界
- 先固定语境:同时记录字符集、排序规则、输入类型和是否显式转换。
- 再看二进制:用
HEX(WEIGHT_STRING(...))观察,不要把终端的不可打印字符当成空结果。 - 最后定用途:它适合测试和调试排序规则,不适合把具体权重字节当作跨 MySQL 版本稳定的业务格式。
还要留意 NULL:输入为 NULL 时函数返回 NULL;非空结果的类型可能是 VARBINARY,长度超过上限时则可能是 BLOB。这些信息能帮助你把“没有看到权重”和“权重是不可打印二进制”区分开。
相关问题
WEIGHT_STRING 能不能替代 ORDER BY?
不建议。它是调试排序规则的函数,官方明确提示行为可能随 MySQL 版本变化。业务排序应直接表达字符列、排序规则和稳定的次排序键。
为什么需要 HEX?
因为返回值是二进制字符串,可能包含不可打印字节;HEX 只是把它转换成便于复制和比较的十六进制文本。
AS CHAR 和 AS BINARY 的 N 有什么区别?
前者按字符计数并使用空格填充,后者按字节计数并使用 0x00 填充;多字节字符下,两者的长度边界不能混用。
-
374 收藏
-
499 收藏
-
384 收藏
-
184 收藏
-
265 收藏
-
443 收藏
-
454 收藏
-
143 收藏
-
209 收藏
-
369 收藏
-
281 收藏
-
400 收藏
-
393 收藏
-
164 收藏
-
257 收藏
-
369 收藏
-
191 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习