使用带有REPLACE选项的LOAD DATA INFILE时,跳过包含非BMP字符(emojis)的行?

时间:2016-11-04 23:34:19

标签: java mysql utf-8

表情符号字符搞乱了我们构建的加载系统,我正在寻找一个简单的短期解决方案。

它是一个Java加载程序,它使用JDBC来执行具有以下结构的MySQL命令:

LOAD DATA
  LOCAL INFILE `filepath` 
  REPLACE INTO TABLE `SOME_TABLE`
  CHARACTER SET utf8
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\'' ESCAPED BY ''
  LINES TERMINATED BY '\n'
(`col1`,...,`coln`)

SOME_TABLE有ENGINE=InnoDB DEFAULT CHARSET=utf8

我们正在运行MySQL 5.6.22。

多年来它一直运行良好,但最近我们加载的文件开始偶尔出现非BMP字符(恰好是emojis)和LOAD DATA LOCAL INFILE ...命令会引发异常,如:

java.sql.SQLException: Incorrect string value: '\xF0\x9D\x93\x9C' for column 'fieldm' at row 3004

据我所知,长期解决方案是我们需要将表格移至CHARSET=utf8mb4。但是,此时表格很大,转换并不容易。索引还有VARCHAR(255)个字段,这些字段需要转换为VARCHAR(191) [以适应最大密钥长度767],或者我们需要转到DYNAMIC行格式并设置innodb_large_prefix=true

我们正在寻找一个短期解决方案,直到我们有时间和资源迁移到utfmb4。

在短期内,可以简单地丢弃具有非BMP(表情符号)字符的行。但是,LOAD DATA LOCAL INFILE filepath REPLACE ...不会跳过坏行,它会使整个文件失败。

此时,看起来我们需要在Java中编写一些过滤来删除非BMP(表情符号)行,然后再调用LOAD DATA LOCAL INFILE filepath REPLACE ...。但是,我认为在MySQL中必须有一些方法可以做到这一点,而不必引入那种预过滤器。

有没有人想要一个简单的方法让MySQL简单地跳过那些包含非BMP(表情符号)数据的行?

*****更新***** 看起来使用CONVERT可能是短期解决方案。这样做会用'????'取代表情符号在col4。

LOAD DATA
  LOCAL INFILE `filepath` 
  REPLACE INTO TABLE `SOME_TABLE`
  CHARACTER SET utf8
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\'' ESCAPED BY ''
  LINES TERMINATED BY '\n'
(`col1`,`col2`,`col3`,@q, ...,  `coln`)
  SET `col4` = CONVERT(CONVERT(@q USING utf8mb4) USING utf8);

有人看到有问题吗?

1 个答案:

答案 0 :(得分:0)

为了存储表情符号,你必须使用utf8mb4,而不是utf8。

191索引问题的快捷方式(可能)是升级到5.7。在那里,你可以保留255 有索引。

只有某些列会持有表情符号,对吗?只转换那些列。 (对于同一个表中的不同列,可以使用不同的字符集和/或排序规则。)