我使用以下命令创建了表 -
create table cust(event int, pid int, REQ_FROM_IP int, REQ_CITY_ID int, REQ_STATE_ID int, REQ_COUNTRY_ID int, key String)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
"separatorChar" = "|",
"quoteChar" = "'",
"escapeChar" = "\\"
)STORED AS TEXTFILE;
但是,创建的表将所有coloumns都作为String!
desc cust;
OK
event string from deserializer
pid string from deserializer
req_from_ip string from deserializer
req_city_id string from deserializer
req_state_id string from deserializer
req_country_id string from deserializer
key string from deserializer
是SerDe搞乱数据结构吗?
答案 0 :(得分:3)
通过仔细阅读源代码,看起来OpenCSVSerde将始终输出字符串列,而不考虑HiveQL查询中实际指定的类型。
一个潜在的(不是非常漂亮的)解决方法可能是使用OpenCSVSerde格式化临时表(该定义可以与您当前对cust
的定义相同,也许称之为cust_staging
如果您的用例是您尝试以该格式加载数据并尝试使用“正确”数据类型在Hive中使用它,则可以填充cust_staging
,就像通常加载表格一样然后使用CTAS语句填充目标表cust
,如:
CREATE TABLE cust AS SELECT
CAST(event AS INT) AS event,
CAST(pid AS INT) AS pid,
CAST(REQ_FROM_IP AS INT) AS REQ_FROM_IP,
CAST(REQ_CITY_ID AS INT) AS REQ_CITY_ID,
CAST(REQ_STATE_ID AS INT) AS REQ_STATE_ID,
CAST(REQ_COUNTRY_ID AS INT) AS REQ_COUNTRY_ID,
key
FROM cust_staging;
现在cust
将包含您期望的列类型:
hive> DESCRIBE cust;
OK
event int
pid int
req_from_ip int
req_city_id int
req_state_id int
req_country_id int
key string
Time taken: 0.546 seconds, Fetched: 7 row(s)
根据@JeremyBeard的优秀输入,如果您没有使用“正确”类型实现数据,cust
实际上可以是一个视图:
CREATE VIEW `cust` -- All the other stuff is the same
要进一步钻取这一推理线,如果您的用例完全是只读的(您永远不必实际修改此数据),您可以将cust_staging
定义为外部表(仍然使用OpenCSVSerde)指向管道分隔的数据文件,然后将cust
定义为此外部表的视图。
但是,如果您的用例是您需要以OpenCSVSerde格式存储具有非字符串列的表,那么您仍然可以创建cust_staging
表(再次,使用您最初的相同定义)和以相反的方向填充数据:
INSERT INTO TABLE cust_staging SELECT * FROM cust;
如果所有这些仍然感觉不够优雅(可理解) - 解决方案可能是将OpenCSVSerde扩展为自定义SerDe,无需中间登台表即可执行您想要的操作。