【问题标题】:SQL Server dump of varchar data to file loads in mysql but not mariadbSQL Server 将 varchar 数据转储到 mysql 但不是 mariadb 中的文件加载
【发布时间】:2018-05-17 12:34:03
【问题描述】:

我通过 cygwin 命令行使用 SQLCMD 将 SQL Server 数据库中的大量字符串数据作为 INSERTS 转储到我的 Windows10 工作站上的文本文件中。

它可以很好地加载到 mysql 中,但是在 mariadb 中我得到了这个错误:

ERROR 1366 (22007) at line 384: 
    Incorrect string value: '\x87ao Su...' for column 'description' at row 1995

我的 SQL Server 数据库有以下设置:

SELECT DISTINCT C.collation_name 
FROM   sys.tables AS T 
       INNER JOIN sys.columns C 
               ON T.object_id = C.object_id 
WHERE  collation_name IS NOT NULL; 

collation_name: Latin1_General_CI_AS

SELECT DISTINCT C.collation_name 
FROM   sys.tables AS T 
       INNER JOIN sys.columns C 
               ON T.object_id = C.object_id 
WHERE  collation_name IS NOT NULL; 
collation_name: Latin1_General_CI_AS

这是 MySQL(它可以愉快地插入):

SHOW FULL COLUMNS FROM forecast
--------------

+--------------------+------------------+-----------------+------+-----+-------------------+----------------+---------------------------------+---------+
| Field              | Type             | Collation       | Null | Key | Default           | Extra          | Privileges                      | Comment |
+--------------------+------------------+-----------------+------+-----+-------------------+----------------+---------------------------------+---------+
| description        | varchar(255)     | utf8_unicode_ci | YES  |     | NULL              |                | select,insert,update,references |         |

SELECT @@character_set_database, @@collation_database, @@collation_connection
--------------

+--------------------------+----------------------+------------------------+
| @@character_set_database | @@collation_database | @@collation_connection |
+--------------------------+----------------------+------------------------+
| utf8                     | utf8_unicode_ci      | utf8_general_ci        |
+--------------------------+----------------------+------------------------+
1 row in set (0.01 sec)

这是来自 MariaDB,它在上面给出了该错误:

SHOW FULL COLUMNS FROM forecast
--------------

+--------------------+------------------+-----------------+------+-----+---------------------+----------------+---------------------------------+---------+
| Field              | Type             | Collation       | Null | Key | Default             | Extra          | Privileges                      | Comment |
+--------------------+------------------+-----------------+------+-----+---------------------+----------------+---------------------------------+---------+
| description        | varchar(255)     | utf8_unicode_ci | YES  |     | NULL                |                | select,insert,update,references |         |
+--------------------+------------------+-----------------+------+-----+---------------------+----------------+---------------------------------+---------+
10 rows in set (0.01 sec)

MariaDB [tardis]> SELECT @@character_set_database, @@collation_database, @@collation_connection;
--------------
SELECT @@character_set_database, @@collation_database, @@collation_connection
--------------

+--------------------------+----------------------+------------------------+
| @@character_set_database | @@collation_database | @@collation_connection |
+--------------------------+----------------------+------------------------+
| utf8                     | utf8_unicode_ci      | utf8_general_ci        |
+--------------------------+----------------------+------------------------+
1 row in set (0.01 sec)

据我所知,MariaDB 的行为应该与 MySQL 相同,但事实并非如此。

我该怎么办?

我可以使用 SQL Server 函数转换文本 - 目前我只是转义 \' 字符 - 但如何?

[UPDATE] 刚刚发现当我从文件中运行 import SQL 命令时,MariaDB 的数据没有任何问题。

只有当我直接在命令行上从 SQLCMD 到 mysql.exe 时才会收到错误消息:

$ SQLCMD.EXE -i "c:\dev\workspace\sql\generate-inserts-for-migration.sql" \
       -h-1 -S "myhost" -d MyDBName -r1 -W \
       -b -f o:65001 | mysql -h myhost.amazonaws.com -u adam -p 

我想这样做,这样我就不必在我的硬盘驱动器上创建一个 10GB 的 SQL 文件,或者我什至可以在同一网络上的 docker 容器(GB 空间有限)中运行它云。

【问题讨论】:

    标签: mysql sql-server mariadb


    【解决方案1】:

    您需要在创建 SQL 文件转储时告诉 sqlcmd 将输出文本转换为 unicode。

    在转储文件时尝试使用-u 标志。

    或者尝试在导入时使用此标志,将 latin-1 转换为 utf-8

     -f i:1252,o:65001
    

    1252 是 microsoft-speak 的 Latin-1 和 68001 的 utf-8。

    顺便说一句,为了让您的 MySQL / MariaDB 数据适应未来,您应该考虑使用 utf8mb4 作为您的字符集,而不仅仅是 utf8。这是一个解释。 What is the difference between utf8mb4 and utf8 charsets in mysql?

    【讨论】:

    • sqlcmd 没有打球。 -u-f o:65001 都没有将输出更改为 mariadb 可以处理的内容。我搜索了转储文件,找不到\x87ao 或类似的东西。它是否可能适用于 mysql,因为我使用 > dump.sql 将转储保存到文件中,但这次对于 mariadb,我只是在命令行上执行 SQLCMD | mysql?我认为不写文件会节省几个小时。
    • \x87 可能是 Latin1 中的字符
    • 在 Latin1 中,C-cedilla 是 \xC7,根据 en.wikipedia.org/wiki/Windows-1252 。您的数据可能在 cp850 中,这是西欧的默认 OEM 字符集。 C-cedill 是 \x87 那里en.wikipedia.org/wiki/Code_page_850
    【解决方案2】:

    特殊字符原来是带有变音符号的 C,如 Curaçao

    在转储文件中看起来像这样

     Cura<87>ao 
    

    使用 SQLCMD -f o:65001 从 SQL Server 导出后,其中 65001 是 Microsoft UTF8 代码页。

    我也试过SQLCMD -f o:1252,因为数据库说它是latin1

    感谢这个出色的答案How can I find Unicode/non-ASCII characters in an NTEXT field in a SQL Server 2005 table?,我发现了特殊字符是什么

    我认为 mySQL(与 MariaDB 相对)只是简单地导入了它而没有抱怨。

    MariaDB docs 告诉我在命令行上适当地设置--default-character-set,所以我尝试了latin1utf8,这两个都不起作用。

    然后我查看了/usr/share/mysql/charsets/Index.xml 中 MariaDB 的一长串字符集,结果发现 cp1250 可以毫无怨言地工作,但它将特殊字符导入为

    命令是mysql --default-character-set=cp1250

    我无法正确导入数据,但至少我现在可以将其导入 MariaDB。

    【讨论】:

    • 或者连接后使用SET NAMES latin1。这声明客户端编码是 latin1。 (这可能与表声明不同;转换是自动的。)
    猜你喜欢
    • 2012-10-16
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    • 2013-10-30
    • 2011-03-05
    相关资源
    最近更新 更多