我的平面文件应该是 UCS-2,但我无法导入 MySQL 数据库

My flat files should be UCS-2, but I can't import into MySQL database

我有 20 个管道分隔的文本文件,我想将其转换为 MySQL 数据库。数据附带的手册说

Owing to the difficulty of displaying data for characters outside of standard Latin Character Sets, all data is displayed using Unicode (UCS-2) character encoding. All CSV files are structured using commercial standards with the preferred format being pipe delimiter (“|”) and carriage return + line feed (CRLF) as row terminators.

我在 Win 8.1 上使用 MySQL Workbench 6.2.5,但手册提供了示例 SQL 服务器脚本来创建二十个表。这是一个。

/****** Object: Table [dbo].[tbl_Company_Profile_Stocks] Script Date:
12/12/2007 08:42:05 ******/
CREATE TABLE [dbo].[tbl_Company_Profile_Stocks](
[BoardID] [int] NULL,
[BoardName] [nvarchar](255) NULL,
[ClientCompanyID] [int] NULL,
[Ticker] [nvarchar](255) NULL,
[ISIN] [nvarchar](255) NULL,
[OrgVisible] [nvarchar](255) NULL
)

我调整如下 MySQL。

/****** Object: Table dbo.tbl_Company_Profile_Stocks Script Date:
12/12/2007 08:42:05 ******/
CREATE TABLE dbo.tbl_Company_Profile_Stocks
(
BoardID int NULL,
BoardName varchar(255) NULL,
ClientCompanyID int NULL,
Ticker varchar(255) NULL,
ISIN varchar(255) NULL,
OrgVisible varchar(255) NULL
);

因为手册上说平面文件是 UCS-2,所以我在创建时将 dbo 架构设置为 UCS-2 default collation。这很好用 AFAIK。失败的是 LOAD INFILE。因为数据是用 CRLF 行结尾的管道分隔的,所以我尝试了以下操作。

LOAD DATA LOCAL INFILE 'C:/Users/Richard/Dropbox/Research/BoardEx_data/unzipped/Company_Profile_Stocks20100416.csv'
INTO TABLE dbo.tbl_company_profile_stocks
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES;

但在这种情况下,现在已导入行并且消息是 0 row(s) affected Records: 0 Deleted: 0 Skipped: 0 Warnings: 0。所以我尝试 \n 换行符。这导入了一些东西,但我的整数值变成了零,文本变得非常宽。消息是 14121 row(s) affected, 64 warning(s): 1366 Incorrect integer value: <snip> Records: 14121 Deleted: 0 Skipped: 0 Warnings: 28257.

如果我在 Sublime Text 3 中打开平面文本文件,Encoding Helper 包会提示该文件具有 UTF-16 LE with BOM 编码。如果我在创建 dbo 架构时用 UTF-16 default collation 重复上述操作,那么我的结果是相同的。

我该如何解决这个问题?编码让我发疯!

可能主要问题是 LOAD DATA 需要此子句(参见 reference):

CHARACTER SET ucs2

如果这还不够,...

  • 你能得到一些 csv 文件的十六进制转储吗?我想确定它真的是 ucs2。 (ucs2很少见,一般都是用utf8传输的。)如果你把文字粘贴到这个论坛时看起来可读,那么它可能是utf8。
  • 没有"dbo" ("database owner"),只有数据库,在MySQL.
  • 请提供SHOW CREATE TABLE tbl_Company_Profile_Stocks
  • (只是建议)不要在 table 名称前加上 "tbl_";与其说清楚,不如说混乱。
  • 为table提供一个PRIMARY KEY

@Rick James 的答案是正确的(即,使用 CHARACTER SET 选项设置 LOAD DATA 的编码)。但就我而言,这不起作用 because MySQL doesn't support UCS-2.

Note

It is not possible to load data files that use the ucs2 character set.

这里有一些适用于此的方法。最后我选择了这个 SQLite 而不是 MySQL,但最后一个解决方案应该适用于 MySQL,或者任何其他接受平面文件的数据库。

SQLiteStudio

在这种情况下,

SQLiteStudio 是最简单的解决方案。我更喜欢命令行解决方案,但 SQLiteStudio GUI 接受 UCS-2 编码和任何定界符。这会将数据保留在 UCS-2 中。

在Windows命令行中转换为ASCII

最简单的 ASCII 转换是在 Windows 命令行中使用 TYPE

for %%f in (*.csv) do (
    echo %%~nf
    type "%%~nf.csv" > "%%~nf.txt"
)

这可能会导致特殊字符出现问题。在我的例子中,它留在单引号和双引号中,导致 SQLite 导入出现一些问题。这是最粗暴的做法。

在 Python

中转换为 ASCII
import codecs
import glob
import os

for fileOld in glob.glob('*.csv'):
    print 'Reading: %s' % fileOld
    fileNew = os.path.join('converted', fileOld)
    with codecs.open(fileOld, 'r', encoding='utf-16le') as old, codecs.open(fileNew, 'w', encoding='ascii', errors='ignore') as new:
        print 'Writing: %s' % fileNew
        for line in old:
            new.write(line.replace("\'", '').replace('"', ''))

这是最可扩展的方法,可以让您更精确地控制要转换或保留的数据。