postgresql COPY和CSV数据/双引号

时间:2012-04-17 17:07:41

标签: postgresql

CSV行示例:

"2012","Test User","ABC","First","71.0","","","0","0","3","3","0","0","","0","","","","","0.1","","4.0","0.1","4.2","80.8","847"

“First”之后的所有值都是数字列。很多NULL值就这样引用了,对吧。

尝试COPY:

copy mytable from 'myfile.csv' with csv header quote '"';

NOPE:ERROR: invalid input syntax for type numeric: ""

嗯,是的。它是一个空值。在COPY尝试2:

copy mytable from 'myfile.csv' with csv header quote '"' null '""';

NOPE:ERROR: CSV quote character must not appear in the NULL specification

有什么可以做的?在运行COPY之前删除文件中的所有双引号?可以做到这一点,但我认为这是一个非常普遍的问题的正确解决方案。

5 个答案:

答案 0 :(得分:11)

虽然有些数据库产品将空字符串视为NULL值,但标准表明它们是不同的,PostgreSQL将它们视为不同。

最好能够生成具有明确表示的CSV文件。虽然可以使用sed或其他东西将文件过滤到良好的格式,但另一个选项是COPY数据输入到text列可以接受的表中空字符串,然后填充目标表。 NULLIF函数可以帮助:http://www.postgresql.org/docs/9.1/interactive/functions-conditional.html#FUNCTIONS-NULLIF - 如果两个参数匹配则返回NULL,如果不匹配则返回第一个值。因此,像NULLIF(txtcol, '')::numeric这样的东西可能适合你。

答案 1 :(得分:6)

作为替代方案,使用

sed 's/""//g' myfile.csv > myfile-formatted.csv
psql 
# copy mytable from 'myfile-formatted.csv' with csv header;

也可以。

答案 2 :(得分:2)

我认为你需要做的就是:

COPY mytable from '/dir/myfile.csv' DELIMITER ',' NULL '' WITH CSV HEADER QUOTE ;

答案 3 :(得分:2)

COPY mytable from '/dir/myfile.csv' DELIMITER ',' NULL '' 
WITH CSV HEADER FORCE QUOTE *;

答案 4 :(得分:0)

这在Python 3.8.X中对我有用

import psycopg2
import csv
from io import StringIO
db_conn = psycopg2.connect(host=t_host, port=t_port,
                           dbname=t_dbname, user=t_user, password=t_pw)
cur = db_conn.cursor()

csv.register_dialect('myDialect',
                     delimiter=',',
                     skipinitialspace=True,
                     quoting=csv.QUOTE_MINIMAL)

with open('files/emp.csv') as f:
    next(f) 
    reader = csv.reader(f, dialect='myDialect') 
    buffer = StringIO()
    writer = csv.writer(buffer, dialect='myDialect') 
    writer.writerows(reader) 
    buffer.seek(0)
    cur.copy_from(buffer, 'personnes', sep=',', columns=('nom', 'prenom', 'telephone', 'email'))
    db_conn.commit()