AWS Athena查询含HTML字段CSV报HIVE_BAD_DATA错误如何解决
问题现象
将自行生成的多份CSV文件上传至S3存储桶,计划通过AWS Athena查询实现多文件合并为单CSV时,抛出如下报错:
HIVE_BAD_DATA: Error parsing column '0': For input string: apples</li><li>Item 1</li><li>Item 2</li><div class=""atlanta"">organges</div> ...
其中description字段存储HTML格式内容,对应的建表语句、查询语句分别如下:
建表语句:
CREATE EXTERNAL TABLE IF NOT EXISTS `default`.`my_table` ( `item_no` double, `description` string, `name` string ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH SERDEPROPERTIES ( 'serialization.format' = ',', 'field.delim' = ',' ) LOCATION 's3://my_location/' TBLPROPERTIES ('has_encrypted_data'='false', 'skip.header.line.count'='1');
查询语句:
select * from my_table where "item_no" < 30000 limit 10
问题根因
报错本质是CSV解析错位:
- 建表使用的
OpenCSVSerde默认以逗号为字段分隔符、双引号为字段包裹符,但description字段存储的HTML内容本身包含大量逗号、未做转义的双引号(比如HTML标签的class属性),解析时Serde会把HTML里的逗号误判为字段分割点,直接把后续的HTML内容错分到第一列item_no。由于item_no定义为数值类型,引擎尝试把HTML字符串转成double时直接抛出解析失败的错误,和报错信息里“解析第0列失败,输入值是apples - xxx”的表现完全吻合。
- 额外细节:查询语句里用双引号包裹
item_no字段的写法不规范,Athena中双引号用于引用区分大小写的标识符,虽然不是这次报错的直接原因,但容易触发字段找不到的额外问题。
排查步骤
- 从S3路径下随机抽1-2份CSV文件,定位存HTML的
description列,检查含逗号、双引号的行是否符合CSV格式规范:标准CSV要求包含分隔符、换行、引号的字段,必须整体用双引号包裹,字段内部的双引号要替换为两个双引号做转义。 - 去掉查询里的where条件,直接执行
select * from my_table limit 10,确认是否全表扫描时就报同样的解析错误,排除单文件损坏、非CSV文件混入路径的问题。 - 确认S3路径下所有CSV的表头行数一致,和建表参数里
skip.header.line.count='1'的配置匹配,避免表头行被当成数据解析。
解决方案
按优先级从高到低操作:
- 修正建表的Serde配置,补全解析参数
OpenCSVSerde需要显式指定分隔符、引号符、转义符才能正确解析带特殊字符的字段,修正后的建表语句如下:
CREATE EXTERNAL TABLE IF NOT EXISTS `default`.`my_table` ( `item_no` double, `description` string, `name` string ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH SERDEPROPERTIES ( 'separatorChar' = ',', 'quoteChar' = '"', 'escapeChar' = '"' ) LOCATION 's3://my_location/' TBLPROPERTIES ( 'has_encrypted_data'='false', 'skip.header.line.count'='1' );
配置说明:如果CSV是用标准双引号自转义规则生成(即字段内部的双引号写为连续两个双引号),
escapeChar就设为";如果是用反斜杠转义内部双引号,就把escapeChar的值改为\\。
- 修正查询语句的标识符写法
不要用双引号包裹普通字段名,直接写字段名或者用反引号包裹即可:
select * from my_table where item_no < 30000 limit 10
- 源文件格式不规范时先做预处理
如果源CSV生成时没有对含特殊字符的字段做包裹转义,不要直接硬解析:- 重新生成CSV时,对所有包含逗号、换行、双引号的字段(尤其是存HTML的
description字段)统一做标准CSV转义后再上传S3。 - 临时排查数据时,可以先把表的所有字段都定义为string类型,绕过Serde的类型校验把数据完整读入,再通过字符串拆分函数手动提取字段、转换类型,避免解析错误直接阻断查询。
- 重新生成CSV时,对所有包含逗号、换行、双引号的字段(尤其是存HTML的
内容的提问来源于stack exchange,提问作者Benjamin
相关产品推荐
相关产品推荐

