我正在尝试使用存储在S3上的引用CSV文件在Athena中创建外部表。问题是,我的CSV包含应该作为INT读取的列中的缺失值。简单的例子:
CSV:
id,height,age,name
1,,26,"Adam"
2,178,28,"Robert"
CREATE TABLE DEFINITION:
CREATE EXTERNAL TABLE schema.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT
SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
'separatorChar' = ",",
'quoteChar' = '"',
'skip.header.line.count' = '1'
)
STORED AS TEXTFILE
LOCATION 's3://mybucket/test_null/unquoted/'
CREATE TABLE
语句运行正常,但只要我尝试查询表格,我就会HIVE_BAD_DATA: Error parsing field value ''
。
我尝试使CSV看起来像这样(引用空字符串):
"id","height","age","name"
1,"",26,"Adam"
2,178,28,"Robert"
但它不起作用。
尝试在'serialization.null.format' = ''
中指定SERDEPROPERTIES
- 无效。
尝试通过TBLPROPERTIES ('serialization.null.format'='')
指定相同内容 - 仍然没有。
当您将所有列指定为STRING
时,它会起作用,但这不是我需要的。
因此,问题是,是否有以任何方式来读取引用的CSV(引用很重要,因为我的真实数据要复杂得多)到Athena并且列规范正确吗?
答案 0 :(得分:3)
处理这些数据的快速而肮脏的方式:
CSV:
id,height,age,name
1,,26,"Adam"
2,178,28,"Robert"
3,123,34,"Bill, Comma"
4,183,38,"Alex"
DDL:
CREATE EXTERNAL TABLE stackoverflow.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n' -- Or use Windows Line Endings
LOCATION 's3://XXXXXXXXXXXXX/'
TBLPROPERTIES ('skip.header.line.count'='1')
;
问题是它没有处理最后一个字段中的引号字符。基于AWS提供的文档,这是有道理的,因为LazySimpleSerDe从Hive给出以下内容。
我怀疑该解决方案正在使用以下SerDe org.apache.hadoop.hive.serde2.RegexSerDe
。
我稍后会处理正则表达式。
修改强>
正如所承诺的正则表达式:
CREATE EXTERNAL TABLE stackoverflow.test_null_unquoted (
id INT,
height INT,
age INT,
name STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "(.*),(.*),(.*),\"(.*)\""
)
LOCATION 's3://XXXXXXXXXXXXXXX/'
TBLPROPERTIES ('skip.header.line.count'='1') -- Does not appear to work
;
注意:RegexSerDe
似乎与TBLPROPERTIES ('skip.header.line.count'='1')
无法正常工作。这可能是由于雅典娜或塞尔德使用的Hive version。在您的情况下,您可能只会排除ID IS NULL
的行。
进一步阅读:
Stackoverflow - remove surrounding quotes from fields while loading data into hive
答案 1 :(得分:0)
不幸的是,在 Athena 中无法同时获得对引用字段的支持和对空值的支持。您必须选择或。
您可以使用 OpenCSVSerDe 并将所有列输入为字符串,这将为您提供对带引号的字段和空字段的 emtpty 字符串的支持。在查询时使用 TRY_CAST
或 CASE/WHEN
转换值。
或者您可以使用 LazySimpleSerDe
并在查询时去除引号。
我会选择 OpenCSVSerDe,因为您始终可以创建包含所有类型转换的视图,并将该视图用于常规查询。
您可以在此处阅读在 Athena 中使用 CSV 的所有细节:The Athena Guide: Working with CSV