我有一个使用latin1
编码的MySQL数据库,并且我在为函数SUBSTRING()
苦苦挣扎,该函数显然是在计算字节数而不是字符,如以下情况所示:
MySQL [hozana]> set names utf8;
Query OK, 0 rows affected (0.00 sec)
MySQL [hozana]> SELECT SUBSTRING('ééééé', 1, 3);
+-------------------------------+
| SUBSTRING('ééééé', 1, 3) |
+-------------------------------+
| ééé |
+-------------------------------+
到目前为止,一切正常,让我们将连接切换为latin1
编码。
MySQL [hozana]> set names latin1;
Query OK, 0 rows affected (0.00 sec)
MySQL [hozana]> SELECT SUBSTRING('ééééé', 1, 3);
+-------------------------------+
| SUBSTRING('ééééé', 1, 3) |
+-------------------------------+
| é� |
+-------------------------------+
我现在发现的唯一方法是在函数SUBSTRING()之前将字符串转换为utf-8,然后再将其转换回latin1。太丑了...
MySQL [hozana]> select convert(cast(convert(substring(convert(cast(convert('éééé' using latin1) as binary) using utf8), 1, 3) using utf8) as binary) using latin1);
+--------------------------------------------------------------------------------------------------------------------------------------------------+
| convert(cast(convert(substring(convert(cast(convert('éééé' using latin1) as binary) using utf8), 1, 3) using utf8) as binary) using latin1) |
+--------------------------------------------------------------------------------------------------------------------------------------------------+
| ééé |
+--------------------------------------------------------------------------------------------------------------------------------------------------+
我的问题是,要使SUBSTRING()
在latin1
中工作,应该进行正确的配置吗?
注意
这是set names
之前和之后的配置:
MySQL [hozana]> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.5.54 |
+-----------+
MySQL [hozana]> set names utf8;
Query OK, 0 rows affected (0.00 sec)
MySQL [hozana]> SHOW SESSION VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
+--------------------------+--------+
MySQL [hozana]> set names latin1;
Query OK, 0 rows affected (0.00 sec)
MySQL [hozana]> SHOW SESSION VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
+--------------------------+--------+
答案 0 :(得分:0)
用户错误。
当您说SET NAMES latin1
时,您是在向MySQL宣布来自客户端(您)的字节是用latin1编码的。但事实并非如此。他们仍然在utf8中。
当您键入ééééé
时,生成的字节是这些 10 字节C3A9C3A9C3A9C3A9C3A9
,这些字节以 10 latin1个字符发送到mysql,即{ {1}}。 ééééé
根据要求删除了前3个字符(但它们是latin1个字符:SUBSTRING
,十六进制éÃ
,然后将它们传送回您的UTF-8客户程序,该客户程序开始解释{ {1}}为C3A9C3
,然后插在无效的UTF-8,十六进制C3上,并用黑色菱形C3A9
(“替换字符”)在终端上插入。
因此,始终要确保通过连接机制中的某些内容或使用é
建立客户端的编码。如果指定不正确,可能会发生各种各样的不良情况。 {this不能直接解决您的问题;但它解决了许多可能发生的其他事情。
哦,另一件事。您说您拥有“带有latin1编码的MySQL数据库”。那没问题。您仍然必须指定(显然)�
或SET NAMES
编码的客户端。当您执行utf8
时,MySQL将转换为列的编码,而当您执行utf8mb4
时,MySQL将以另一种方式转换回。由于INSERT
和SELECT
中都存在é
(对于所有其他西欧带重音符号的字母也是如此),所以一切都应该很好。
也许您用文字来编写问题。好吧,这不一定反映表中的latin1
。因此,我精心制作了一个表,其中既包含latin1列又包含utf8列,每个列均包含utf8
,并验证了十六进制和LENGTH是不同的。然后在两种情况下测试SELECTing
都会正确产生ééééé
。