首页 > 解决方案 > postgreSQL - 导入 CSV,但列中有逗号

问题描述

我正在使用 postgreSQL 版本 13.0.1。(我必须使用 postgre)

表结构

CREATE TABLE public.orders
(
    key integer NOT NULL,
    skey integer NOT NULL,
    status character(1) COLLATE pg_catalog."default" NOT NULL,
    price numeric(15,2) NOT NULL,
    date date NOT NULL,
    priority character(15) COLLATE pg_catalog."default" NOT NULL,
    man character(15) COLLATE pg_catalog."default" NOT NULL,
    priority2 integer NOT NULL,
    comment character varying(79) COLLATE pg_catalog."default" NOT NULL
)

TABLESPACE pg_default;

ALTER TABLE public.orders
    OWNER to postgres;

CSV 文件内容。第一行是标题,第二行是数据:

key ,skey,  status , price , date       ,priority2        ,man,             priority   ,comment
1   ,2   ,  3      , 45.33 , 1992-02-21 ,4-NOT SPECIFIED  ,man#000000058  , 0          ,ggle. so, whatever you say.

我的查询

COPY public.orders FROM 'D:\orders.csv' WITH (format csv,Header);

错误:

ERROR:  extra data after last expected column
CONTEXT:  COPY orders, line 3: "1,2,3,45.33,1992-02-21,4-NOT SPECIFIED,man#000000058,0,ggle. so, whatever you say.
"
SQL state: 22P04

错误可能是由于最后一列有一个字符串(ggle。所以,不管你说什么。)没有“”将其标记为字符串。它也有一个逗号。

我想要的输出是让查询成功完成,最后一列作为一个完整的字符串读取。我也不允许更改文件中的数据。

我已经尝试了这些链接的建议:
Importing CSV and commas in string values
https://www.postgresql.org/docs/13/sql-copy.html

但我仍然以上面提到的查询和错误结束。请赐教。

标签: postgresqlcsv

解决方案


我会以间接的方式做到这一点。这是一个插图:

  1. 创建一个只有一个文本列的临时表
create temporary table dropme_later (full_line text);
  1. 将文本文件的内容读入dropme_later,每一行读入一列full_line
copy dropme_later from 'D:\orders.csv' 
with
(
 format 'csv',
 header 'true',
 delimiter E'\b'
);

注意分隔符设置为数据中没有出现的字符,即退格;

  1. 使用查询和最后一列的转换dropme_later将数据从其中传输。public.orders这为您提供了很大的自由度和灵活性来使用选择表达式、where 子句等。在这种情况下,首先将每一行拆分为一个数组,然后使用数组表达式。
with t(a) as 
(
 select string_to_array(full_line, ',') from dropme_later
)
insert into public.orders 
select
  a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8],
  array_to_string(a[9:11], ',')
from t;

希望这可以帮助。一个提示 - 有一个很好的 FDW - file_text_array_fdw - 在 ETL 案例中可能会有很大帮助。


推荐阅读