1

这很奇怪。根据 MySQL 开发者网站 -

MySQL CHAR_LENGTH(str)

返回字符串 str 的长度,以字符为单位。多字节字符计为单个字符。这意味着对于包含五个 2 字节字符的字符串,LENGTH() 返回 10,而 CHAR_LENGTH() 返回 5。

这显然意味着 CHAR_LENGTH(str) 的输出与字符集无关。

现在如给出 -

字符串文字字符集和排序规则

我可以使用介绍器来设置字符串的 SET CHARACTER SET,如 -

选择“ABC”;
选择_latin1'abc';
选择 _binary'abc';
选择 _utf8mb4'abc' 整理 utf8mb4_danish_ci;

就我而言,我采用字符串文字“Hello”,使用介绍器将其设置为 CHARACTER SET,并将其用作 MySQL CHAR_LENGTH(str) 函数的参数。但奇怪的是,当使用不同的字符集时,它有时会产生不同的输出。例子 -

SELECT CHAR_LENGTH(_utf8mb4"Hello") AS character_length;
+------------------+
| character_length |
+------------------+
|                5 |
+------------------+

SELECT CHAR_LENGTH(_latin1"Hello") AS character_length;
+------------------+
| character_length |
+------------------+
|                5 |
+------------------+

SELECT CHAR_LENGTH(_ucs2"Hello") AS character_length;
+------------------+
| character_length |
+------------------+
|                3 |
+------------------+

这里,“你好”有 5 个字符。CHARACTER SETS _utf8mb4 和 _latin1 正确显示字符数。但是 CHARACTER SET _ucs2 奇怪地将数字 0f 字符显示为 3。

这是怎么回事?

4

2 回答 2

1

看起来像一个错误:

SELECT HEX(_ucs2"HELLO"), HEX(CONVERT("HELLO" USING ucs2));
+-------------------+----------------------------------+
| HEX(_ucs2"HELLO") | HEX(CONVERT("HELLO" USING ucs2)) |
+-------------------+----------------------------------+
| 0048454C4C4F      | 00480045004C004C004F             |
+-------------------+----------------------------------+

介绍人似乎_ucs2只适用于第一个字符。

我创建了错误https://bugs.mysql.com/bug.php?id=105394&thanks=4

来自错误报告

_charset_name 表达式正式称为介绍器。它告诉解析器,“后面的字符串使用字符集 charset_name。” 介绍人不会像 CONVERT() 那样将字符串更改为介绍人字符集。它不会更改字符串值,尽管可能会发生填充。介绍人只是一个信号。

于 2021-10-31T23:35:38.117 回答
1

那是因为显示的语言,该词需要 3 个字符。

扩展我的答案。

字符转换在最好的情况下是困难的,应该不惜一切代价避免。

首先 MySQL 尝试将 $ Byte characte4r 转换为 ucs2 具有的 2 Byte 字符。

然后使用生成的字节来显示字符,即您在代码段末尾看到的内容。

因此,在字符集的转换中,您在计算机科学字节中没有随处可见的字母,用 H 的表示来表示,但另一个字符集中的字节可能有另一种表示。此外,如果字节数不同,您总是需要一些规则,如何将一个字符集转换为另一个字符集。

因此,我还扩展了示例,向您展示实际发生的确定性转换,如果您查看字节或二进制表示,您会发现使用的具体算法。

SELECT CHAR_LENGTH(_ucs2"Hello") AS character_length;
| 字符长度 |
| ---------------: |
| 3 |
SELECT _ucs2"Hello";
| 䡥汬 |
| :-------- |
| H敬汯 |
SELECT _ucs2"Hel";
| 䡥 |
| :--- |
| H敬 |
SELECT _ucs2"Hell";
| 䡥汬 |
| :----- |
| 䡥汬 |
SELECT _ucs2"Hellos";
| 䡥汬潳 |
| :-------- |
| 䡥汬潳 |

db<>在这里摆弄

于 2021-10-30T00:05:18.603 回答