【问题标题】:Hive load CSV with commas in quoted fieldsHive 在带引号的字段中使用逗号加载 CSV
【发布时间】:2012-11-17 16:42:44
【问题描述】:

我正在尝试将 CSV 文件加载到 Hive 表中,如下所示:

CREATE TABLE mytable
(
num1 INT,
text1 STRING,
num2 INT,
text2 STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ",";

LOAD DATA LOCAL INPATH '/data.csv'
OVERWRITE INTO TABLE mytable;    


csv 由逗号 (,) 分隔,如下所示:

1, "some text, with comma in it", 123, "more text"

这将返回损坏的数据,因为第一个字符串中有一个“,”。
有没有办法设置文本分隔符或让 Hive 忽略字符串中的“,”?

我无法更改 csv 的分隔符,因为它是从外部源提取的。

【问题讨论】:

    标签: hadoop hbase hive hdfs delimiter


    【解决方案1】:

    如果您可以重新创建或解析输入数据,则可以为 CREATE TABLE 指定转义字符:

    ROW FORMAT DELIMITED FIELDS TERMINATED BY "," ESCAPED BY '\\';
    

    将接受这一行作为 4 个字段

    1,some text\, with comma in it,123,more text
    

    【讨论】:

    • 处理嵌入的逗号,但不处理嵌入的换行符,这是 CSV 数据中的另一个问题。或者换行符也可以转义? cwiki.apache.org/confluence/display/Hive/… 的规范似乎不允许转义换行符。
    • 非常感谢,这对我有用。为了重新创建 csv 文件,我使用 python csv writer 和以下方言 csv.register_dialect('for_hive', escapechar='\\', quoting=csv.QUOTE_NONE)
    【解决方案2】:

    问题是Hive 不处理引用的文本。您需要通过更改字段之间的分隔符来预处理数据(例如:使用 Hadoop 流作业),或者您也可以尝试使用自定义 CSV SerDe,它使用 OpenCSV 解析文件。

    【讨论】:

    • sed -i 's/"//g' your_file_name 通过删除引用的文本就地进行预处理。但是,您需要确定没有无害地删除其他预期引用的 ( ") 个字符。
    【解决方案3】:

    从 Hive 0.14 开始,CSV SerDe 是 Hive 安装的标准部分

    ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'

    (参见:https://cwiki.apache.org/confluence/display/Hive/CSV+Serde

    【讨论】:

    • 如果您的 HIVE 是最新的,这是最好的答案 :)
    • 这对我也有帮助!
    • 当您使用 OpenCSVSerde 时,有没有办法指定 Null 的定义是什么?使用“ROW FORMAT DELIMITED”,我可以添加选项“NULL DEFINED AS ''”来识别数据中的空值。
    • 这对我不起作用,Hive 将引用的值显示为 NULL
    • @wrschneider,我在哪里可以下载这个 serde?​​span>
    【解决方案4】:

    将分隔符保留在单引号中,它会起作用。

    ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY ','
    LINES TERMINATED BY '\n';
    

    这会起作用

    【讨论】:

      【解决方案5】:

      在 FIELDS TERMINATED BY '\;' 中添加反斜杠

      例如:

      CREATE  TABLE demo_table_1_csv
      COMMENT 'my_csv_table 1'
      ROW FORMAT DELIMITED
      FIELDS TERMINATED BY '\;'
      LINES TERMINATED BY '\n'
      STORED AS TEXTFILE
      LOCATION 'your_hdfs_path'
      AS 
      select a.tran_uuid,a.cust_id,a.risk_flag,a.lookback_start_date,a.lookback_end_date,b.scn_name,b.alerted_risk_category,
      CASE WHEN (b.activity_id is not null ) THEN 1 ELSE 0 END as Alert_Flag 
      FROM scn1_rcc1_agg as a LEFT OUTER JOIN scenario_activity_alert as b ON a.tran_uuid = b.activity_id;
      

      我已经测试过了,它确实有效。

      【讨论】:

      • 因为'\;'';' 相同,所以它可以工作。没有必要转义分号 - 但也没有必要
      【解决方案6】:

      ORG.APACHE.HADOOP.HIVE.SERDE2.OPENCSVSERDE Serde 为我工作。我的分隔符是“|”并且其中一列用双引号括起来。

      查询:

      CREATE EXTERNAL TABLE EMAIL(MESSAGE_ID STRING, TEXT STRING, TO_ADDRS STRING, FROM_ADDRS STRING, SUBJECT STRING, DATE STRING)
      ROW FORMAT SERDE 'ORG.APACHE.HADOOP.HIVE.SERDE2.OPENCSVSERDE'
      WITH SERDEPROPERTIES (
           "SEPARATORCHAR" = "|",
           "QUOTECHAR"     = "\"",
           "ESCAPECHAR"    = "\""
      )    
      STORED AS TEXTFILE location '/user/abc/csv_folder';
      

      【讨论】:

      • 它使用模式中的所有字符串创建表
      猜你喜欢
      • 2017-12-22
      • 1970-01-01
      • 2014-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多