java - 使用带有 REPLACE 选项的 LOAD DATA INFILE 时跳过包含非 BMP 字符(表情符号)的行?

标签 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 字符(恰好是表情符号),并且 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) [以适应最大 key 长度 767],否则我们需要为 DYNAMIC 行格式并设置 innodb_large_prefix=true

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

从短期来看,只需丢弃包含非 BMP(表情符号)字符的行就可以了。但是,LOAD DATA LOCAL INFILE filepath REPLACE ... 不会跳过坏行,它会使整个文件失败。

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

有人有什么想法可以让 MySQL 简单地跳过包含非 BMP(表情符号)数据的行吗?

***** 更新 ***** 看起来使用 CONVERT 可能是短期的解决方案。这样做会将表情符号替换为“???”在第4 栏。

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);

有人发现这有问题吗?

最佳答案

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

解决 191 索引问题的捷径(也许)是升级到 5.7。在那里,您可以保留 255 并且有索引。

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

关于java - 使用带有 REPLACE 选项的 LOAD DATA INFILE 时跳过包含非 BMP 字符(表情符号)的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40433141/

相关文章:

mysql - 0000-00-00 00 :00:00 date in table when is set to be NOT NULL

perl - 使用 'use utf8;' 给我 'Wide character in print'

php - PostgreSQL + PHP + UTF8 = 编码的无效字节序列

php - 如何使用带有 for 循环的 php 从关联数组创建 html 表?

mysql - group by() 和 group by 的区别

mysql - 替换mysql数据库中的字符

java - 在 android Studio 上处理来自 AlertDialog 的 userInput

Java <key, value> 集合在 O(1) 或 O(log(n)) 最坏情况下检索最小元素

java - 一项 Activity 2 个按钮,可以进行不同的 Activity

java - 无法从 Java 中匹配的 * 组中检索数据