【发布时间】: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 |
+----------------------------------------+
| ßńŔ´ÚÝňż˛ˇ˘Ó°ÜŁ˙ ř×┴ ╚¤╔═┼╝ĎË └ěŐŹ┌ ŢÄ |
+----------------------------------------+
这就像从文件导入时编码搞砸了。或者在通过 Keyboard 或 Clipboard 输入到 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 保存脚本文件。您可以使用记事本来执行此操作。