如何用SQL的LENGTH和CHAR_LENGTH函数区分并获取字符串字节长度的不同之处?

2026-04-24 20:072阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计895个文字,预计阅读时间需要4分钟。

如何用SQL的LENGTH和CHAR_LENGTH函数区分并获取字符串字节长度的不同之处?

在MySQL中,`LENGTH()` 和 `CHAR_LENGTH()` 都可以用来计算字符串长度,但它们的意义有所不同。`LENGTH()` 返回的是字符串的物理字节长度,而 `CHAR_LENGTH()` 返回的是字符的个数。

如果你关心的是这个字段实际占多少存储空间或是否超出VARBINARY限制,你应该使用 `LENGTH()`,因为它的值包括了所有字符的编码字节。

如果你只关心有几个汉字/字母,应该使用 `CHAR_LENGTH()`,因为它不考虑字符编码的长度差异。

简而言之:

根本原因在于 MySQL 的字符集处理方式:UTF8MB4 下,一个汉字占 3 或 4 字节,而 LENGTH() 按字节计数,CHAR_LENGTH() 按 Unicode 字符计数(无论多长)。

中文、emoji 场景下 LENGTH 明显大于 CHAR_LENGTH

执行这条语句就能直观看到差异:

SELECT '你好?' AS str, LENGTH('你好?') AS byte_len, CHAR_LENGTH('你好?') AS char_len;

结果通常是:byte_len = 10(“你好”各 3 字节 + ? 占 4 字节),char_len = 3(两个汉字 + 一个 emoji 算一个字符)。

  • 若字段定义为 VARCHAR(10),存得下这个字符串(字符数没超)
  • 但若底层是 VARBINARY(10) 或做 HTTP header 截断逻辑,10 字节根本装不下 —— 这时只看 CHAR_LENGTH() 就会出错
  • 某些旧系统用 LENGTH() 做密码哈希前校验长度,UTF8MB4 下可能误判超长

PostgreSQL 和 SQL Server 不叫 CHAR_LENGTH

MySQL 的 CHAR_LENGTH() 在 PostgreSQL 里叫 CHAR_LENGTH()(同名),但 SQL Server 只有 LEN() —— 它的行为等价于 MySQL 的 CHAR_LENGTH(),不提供原生字节长度函数。SQL Server 要算字节长度得绕一下:

SELECT DATALENGTH(N'你好?'); -- 返回 10,注意必须用 N'' 前缀表示 Unicode

Oracle 用 LENGTHB() 表示字节长度,LENGTH() 默认是字符长度(和 MySQL 相反)。

  • 跨数据库写迁移脚本时,别直接复制 LENGTH() —— 先确认目标库的默认语义
  • MySQL 5.7+ 默认字符集是 utf8mb4,LENGTH() 的结果比老版本更“膨胀”,升级后要重测长度校验逻辑

WHERE 条件里混用 LENGTH 和 CHAR_LENGTH 可能导致索引失效

如果在 WHERE 子句里对字段套 LENGTH(col) > 10,即使 col 有索引,MySQL 通常也无法走索引(属于对列做函数运算)。而 CHAR_LENGTH(col) > 10 同样如此。

  • 真要按长度过滤且需性能,建议加生成列:ALTER TABLE t ADD COLUMN byte_len INT AS (LENGTH(str_col)) STORED,再给它建索引
  • 或者业务层提前计算好长度存到单独字段,避免每次查都算
  • 特别注意:JSON 字段用 LENGTH(json_col) 返回的是整个 JSON 文本的字节数,不是里面某个 key 的值长度

实际用哪个,取决于你到底在约束什么:是磁盘空间、网络传输、协议限制(字节),还是用户感知、显示宽度、业务规则(字符)。两者差的那几个字节,常常就是线上截断、乱码、越界报错的源头。

标签:字节

本文共计895个文字,预计阅读时间需要4分钟。

如何用SQL的LENGTH和CHAR_LENGTH函数区分并获取字符串字节长度的不同之处?

在MySQL中,`LENGTH()` 和 `CHAR_LENGTH()` 都可以用来计算字符串长度,但它们的意义有所不同。`LENGTH()` 返回的是字符串的物理字节长度,而 `CHAR_LENGTH()` 返回的是字符的个数。

如果你关心的是这个字段实际占多少存储空间或是否超出VARBINARY限制,你应该使用 `LENGTH()`,因为它的值包括了所有字符的编码字节。

如果你只关心有几个汉字/字母,应该使用 `CHAR_LENGTH()`,因为它不考虑字符编码的长度差异。

简而言之:

根本原因在于 MySQL 的字符集处理方式:UTF8MB4 下,一个汉字占 3 或 4 字节,而 LENGTH() 按字节计数,CHAR_LENGTH() 按 Unicode 字符计数(无论多长)。

中文、emoji 场景下 LENGTH 明显大于 CHAR_LENGTH

执行这条语句就能直观看到差异:

SELECT '你好?' AS str, LENGTH('你好?') AS byte_len, CHAR_LENGTH('你好?') AS char_len;

结果通常是:byte_len = 10(“你好”各 3 字节 + ? 占 4 字节),char_len = 3(两个汉字 + 一个 emoji 算一个字符)。

  • 若字段定义为 VARCHAR(10),存得下这个字符串(字符数没超)
  • 但若底层是 VARBINARY(10) 或做 HTTP header 截断逻辑,10 字节根本装不下 —— 这时只看 CHAR_LENGTH() 就会出错
  • 某些旧系统用 LENGTH() 做密码哈希前校验长度,UTF8MB4 下可能误判超长

PostgreSQL 和 SQL Server 不叫 CHAR_LENGTH

MySQL 的 CHAR_LENGTH() 在 PostgreSQL 里叫 CHAR_LENGTH()(同名),但 SQL Server 只有 LEN() —— 它的行为等价于 MySQL 的 CHAR_LENGTH(),不提供原生字节长度函数。SQL Server 要算字节长度得绕一下:

SELECT DATALENGTH(N'你好?'); -- 返回 10,注意必须用 N'' 前缀表示 Unicode

Oracle 用 LENGTHB() 表示字节长度,LENGTH() 默认是字符长度(和 MySQL 相反)。

  • 跨数据库写迁移脚本时,别直接复制 LENGTH() —— 先确认目标库的默认语义
  • MySQL 5.7+ 默认字符集是 utf8mb4,LENGTH() 的结果比老版本更“膨胀”,升级后要重测长度校验逻辑

WHERE 条件里混用 LENGTH 和 CHAR_LENGTH 可能导致索引失效

如果在 WHERE 子句里对字段套 LENGTH(col) > 10,即使 col 有索引,MySQL 通常也无法走索引(属于对列做函数运算)。而 CHAR_LENGTH(col) > 10 同样如此。

  • 真要按长度过滤且需性能,建议加生成列:ALTER TABLE t ADD COLUMN byte_len INT AS (LENGTH(str_col)) STORED,再给它建索引
  • 或者业务层提前计算好长度存到单独字段,避免每次查都算
  • 特别注意:JSON 字段用 LENGTH(json_col) 返回的是整个 JSON 文本的字节数,不是里面某个 key 的值长度

实际用哪个,取决于你到底在约束什么:是磁盘空间、网络传输、协议限制(字节),还是用户感知、显示宽度、业务规则(字符)。两者差的那几个字节,常常就是线上截断、乱码、越界报错的源头。

标签:字节