【问题标题】:Using source command corrupts non Unicode text encoding使用 source 命令会破坏非 Unicode 文本编码
【发布时间】:2017-10-13 13:52:32
【问题描述】:

我必须将一些包含未编码为 Unicode 的国家字符的数据导入独立的 MySQL 版本:在 Windows7 64 位上运行的 5.0.18。在一些最初的问题之后,我终于让它在 MySQL 控制台中工作了。

但由于数据超过 50 MByte,因此无法在控制台中输入或使用剪贴板。所以我创建了脚本文件才发现导入后国家字符是乱码。

问题是,如果我对任何文件使用source 命令,编码就会中断。如果我打开同一个文件并通过剪贴板将内容复制到控制台,所有工作都应该正常。这里最小的 MCVE 来测试这个:

DROP DATABASE IF EXISTS dbs;
CREATE DATABASE dbs;
USE dbs;

SET NAMES latin2;

DROP TABLE IF EXISTS `tab`;
CREATE TABLE `tab` (`ix` INT default 0,`nam` VARCHAR(50) default '' );
INSERT INTO `tab` VALUES
 (1,'aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ'),
 (2,'áäčďéíĺľňóôŕřšťú ýžÁ ČĎÉÍĹĽŇÓ ŔŘŠŤÚ ÝŽ');
SELECT * FROM `tab`;

当我通过 剪贴板 将其复制到 MySQL 控制台时,输出如下:

+------+----------------------------------------+
| ix   | nam                                    |
+------+----------------------------------------+
|    1 | aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ |
|    2 | áäčďéíĺľňóôŕřšťú ýžÁ ČĎÉÍĹĽŇÓ ŔŘŠŤÚ ÝŽ |
+------+----------------------------------------+
2 rows in set (0.00 sec)

这是需要的。但是当我将所有这些放入test.sql 文件并运行时

source test.sql;

我得到了这个输出:

+------+----------------------------------------+
| ix   | nam                                    |
+------+----------------------------------------+
|    1 | aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ |
|    2 | ßńŔ´ÚÝňż˛ˇ˘Ó°ÜŁ˙ ř×┴ ╚¤╔═┼╝ĎË └ěŐŹ┌ ŢÄ |
+------+----------------------------------------+

这显然是错误的(看起来像一些默认的 MS-DOS 字符集)。我认为问题不在于表格或数据库,因为这对于纯文本输出是相同的,例如:

SET NAMES latin2;
SELECT 'áäčďéíĺľňóôŕřšťú ýžÁ ČĎÉÍĹĽŇÓ ŔŘŠŤÚ ÝŽ' AS 'aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ';

哪些输出带有剪贴板:

+----------------------------------------+
| aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ |
+----------------------------------------+
| áäčďéíĺľňóôŕřšťú ýžÁ ČĎÉÍĹĽŇÓ ŔŘŠŤÚ ÝŽ |
+----------------------------------------+

还有source 文件:

+----------------------------------------+
| aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ |
+----------------------------------------+
| ßńŔ´ÚÝňż˛ˇ˘Ó°ÜŁ˙ ř×┴ ╚¤╔═┼╝ĎË └ěŐŹ┌ ŢÄ |
+----------------------------------------+

这就像从文件导入时编码搞砸了。或者在通过 KeyboardClipboard 输入到 MySQL 控制台时,编码发生了变化。

那么发生了什么以及如何纠正这个问题(不丢失数据)?

  • 使用< 命令行选项而不是source 没有帮助
  • source 使用-e 命令行选项没有帮助
  • 使用默认字符集命令行选项没有帮助
  • 对非 Unicode 字符串使用 UTF8 会导致 Data too long errors 和数据丢失
  • 剪贴板中的数据与文件中的相同

[编辑1]

好吧,我尝试了较新版本的 MySQL 5.7.19,由于他们更改了初始化和其他内容,我花了很长时间才开始使用(wtf?那个疯狂的东西在没有任何数据的情况下得到了 1.8 GByte!)。无论我做什么,它的行为都是一样的。所以我尝试使用 UTF8 编码:

DROP DATABASE IF EXISTS dbs;
CREATE DATABASE dbs CHARACTER SET utf8 COLLATE 'utf8_unicode_ci';
USE dbs;

SET NAMES utf8;

DROP TABLE IF EXISTS `tab`;
CREATE TABLE `tab` (`ix` INT default 0,`nam` VARCHAR(50) default '' ) CHARACTER SET utf8 COLLATE 'utf8_unicode_ci';
INSERT INTO `tab` VALUES
 (1,'áäčďéíĺľňóôŕřšťú ýžÁ ČĎÉÍĹĽŇÓ ŔŘŠŤÚ ÝŽ'),
 (2,'aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ');
SELECT * FROM `tab`;

#SELECT 'áäčďéíĺľňóôŕřšťú ýžÁ ČĎÉÍĹĽŇÓ ŔŘŠŤÚ ÝŽ' AS 'aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ';

#SHOW COLLATION;
#SHOW CHARACTER SET;
SHOW VARIABLES LIKE 'char%';

是的,脚本文件被转换为 UTF8。现在这里是 my.ini 设置:

[mysql]

 default-character-set=utf8

[mysqld]

 skip-character-set-client-handshake
 character-set-server=utf8
 collation-server=utf8_unicode_ci

终于为使用source的文件工作了,结果如下:

+------+--------------------------------------------------------------------------+
| ix   | nam                                                                      |
+------+--------------------------------------------------------------------------+
|    1 | áäčďéíĺľňóôŕřšťú ýžÁ ČĎÉÍĹĽŇÓ ŔŘŠŤÚ ÝŽ                                   |
|    2 | aacdeillnoorrstuuyzAACDEILLNOORRSTUUYZ                                   |
+------+--------------------------------------------------------------------------+
+--------------------------+--------------------------------------------------------------------+
| Variable_name            | Value                                                              |
+--------------------------+--------------------------------------------------------------------+
| character_set_client     | utf8                                                               |
| character_set_connection | utf8                                                               |
| character_set_database   | utf8                                                               |
| character_set_filesystem | binary                                                             |
| character_set_results    | utf8                                                               |
| character_set_server     | utf8                                                               |
| character_set_system     | utf8                                                               |
+--------------------------+--------------------------------------------------------------------+

【问题讨论】:

  • MySQL 和脚本是否同意字符编码?看起来数据库正在使用与保存时不同的字符编码来解释脚本文件。
  • @IInspectable 是的..但是如何改变它或强迫它做它应该做的事情?唯一传递所有条目的字符集是 latin2,它与数据源一致,但通过文件传递会破坏它......就像可能在 Windows 端将它重新编码为不同的字符集......
  • 尝试使用带有 BOM 的 UTF-8 保存脚本文件。您可以使用记事本来执行此操作。

标签: mysql windows


【解决方案1】:

您必须在创建表时指定CHARACTER SET,最好是在列本身上。否则,您会从 SHOW VARIABLES LIKE 'char%'; 获得一些默认值

SET NAMES 在客户端建立编码。

INSERTingSELECTing 时,编码从客户端的编码 (SET NAMES) 更改为列的编码 (... VARCHAR ... CHARACTER SET ...)。

你真的需要 latin2 吗?世界正在转向 UTF-8。

【讨论】:

  • 我添加了带有 UTF8 解决方案的 edit1。无论我做什么,latin2 都不起作用。我想首先使用 UTF8,但我无法让它与旧的 MySQL 版本一起工作(即使它应该工作但 my.ini 设置被忽略了)。我升级到5.7.19 并且 UTF8 的东西终于可以工作了(但是 latin2 仍然不行)所以我认为这已经解决了。由于您回答中的查询将我引向解决方案,因此我接受您的回答。
  • 是的,这是一个挑战。正如stackoverflow.com/questions/38363566/… 的“最佳实践”中所指出的,有6 个地方需要指定字符集。其他事情以大约 5 种不同的方式发生故障。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-12
  • 2013-07-01
相关资源
最近更新 更多