1、问题描述
自动化调度系统在按周期天执行数据迁移(出库)任务时,在执行到某条SQL时报错,最终导致任务失败
SQL如下(已转化):
insert table t1
select
dt,
id,
name,
counts,
roles,
comments
from t2
where dt='20240101'
报错信息摘要如下:
Error message from spark is:java.io.IOException: ERROR-1-HIVE:20027:{Failed to execute move task of sparkSql}Moving data to: hdfs://...
move task failed to execute => Failed with exception ERROR: syntax error at or near ":" 位置:384
报错信息提示语法问题,可是检查SQL发现也没有什么语法问题,这到底是怎么回事呢?
2、问题原因
最终,从SQL和表的角度入手,首先,检查SQL里面的查询语句的执行:
select
dt,
id,
name,
counts,
roles,
comments
from t2
where dt='20240101'
使用Presto引擎的执行的结果:
dt | id | name | counts | roles | comments |
---|---|---|---|---|---|
20240101 | 18 | A | 630 | 伍六七 青凤 江惠莲 | 793 |
使用Hive(MapReduce)和Spark引擎执行的结果:
dt | id | name | counts | roles | comments |
---|---|---|---|---|---|
20240101 | 18 | A | 630 | 伍六七 | NULL |
青凤 | NULL | NULL | NULL | NULL | NULL |
江惠莲 | 793 | NULL | NULL | NULL | NULL |
从上面结果可以看到,若Hive表字段值中存在换行符,MapReduce和Spark引擎的查询结果出现混乱
由于我们的调度系统设置的执行引擎为Spark,因此,原本查询的一行结果会被字段值中的换行符\n
转换为多行,查询结果结构混乱,最终导致插入失败
3、问题解决
Hive提供了regexp_replace()
函数可用于替换数据仓库中包含特殊字符(如换行符)的字段
Hive字符串UDF官网:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF#LanguageManualUDF-StringFunctions
根据官网描述,换行符\n
使用两个反斜杠,即一个反斜杠用来转义
修改后的SQL如下:
insert table t1
select
dt,
id,
name,
counts,
regexp_replace(roles, '\\n', ' ') as roles,
comments
from t2
where dt='20240101'
这样,我们的数据才会显示正常,报错问题也就解决了
另外,部分系统可能需要使用四个反斜杠,即
regexp_replace(col, '\\\\n', ' ')
以下是一些常见的特殊符号:
-
常见换行:
\n
换行,\r
回车、\r\n
回车并换行 -
ASCII中的换行:
\x0A
(10,\n
),\x0D
(13,\r
) -
三种Unicode空格:
\u00A0
不间断空格:主要用于Office中,让一个单词在结尾处不会换行显示\u0020
半角空格(英文符号):代码中常用的空格\u3000
全角空格(中文符号):中文文章中使用的空格
以下是使用Java正则表达式语法匹配多个子字符串替换的示例:
regexp_replace(col, '\\n|\\u00a0', ' ')