Postgres在COPY中不允许使用ARRAY语法

时间:2016-08-18 18:44:28

标签: arrays postgresql csv etl psycopg2

我有一个包含文本数组(text[])类型列的表。我想使用COPY命令复制CSV。我使用Psycopg2的复制功能,但问题一般与Postgres有关。

似乎Postgres只接受格式为{"string1","string2","string3"}的数组,而不是ARRAY['string1', 'string2', 'string3'](见下文)。这是一个问题,因为以前格式转义的字符串是一个巨大的痛苦,而Psycopg2的mogrify函数以后一种格式输出数组。第一种格式的手动转义是我的最后一招,但我真的不想去那里......

有没有办法让Postgres采用后一种格式进行复制或其他一些解决方法?

以下是我的测试:

-- proof that both syntaxes are valid and compare equal
db=# SELECT ARRAY['string1', 'string2', 'string3']::text[] = '{"string1","string2","string3"}'::text[];
 ?column?
----------
 t
(1 row)

-- COPY works with {} syntax
db=# CREATE TEMP TABLE test(words text[]);
CREATE TABLE
db=# COPY test FROM stdin;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> {"string1","string2","string3"}
>> \.
COPY 1

-- COPY fails with ARRAY syntax
db=# COPY test FROM stdin;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> ARRAY['string1', 'string2', 'string3']
>> \.
ERROR:  malformed array literal: "ARRAY['string1', 'string2', 'string3']"
DETAIL:  Array value must start with "{" or dimension information.
CONTEXT:  COPY test, line 1, column words: "ARRAY['string1', 'string2', 'string3']"

2 个答案:

答案 0 :(得分:3)

使您的数据成为元组列表:

data = [
    (1, ['a','b']),
    (2, ['c','d'])
]

创建values语法模板以接收数据元组:

values_template = ','.join(['%s'] * len(data))

将其放入copy命令:

copy_values = "copy (values {0}) to stdout (format csv)".format(values_template)

使用mogrify使Python类型适应Postgresql类型:

copy_values = cursor.mogrify(copy_values, data)

copy_expert导出文件:

f = open('file.csv', 'wb')
cursor.copy_expert(copy_values, f, size=8192)
f.close()

答案 1 :(得分:1)

第一次测试(证明)并不正确。在这种情况下,这应该是测试:

SELECT 'ARRAY["string1", "string2", "string3"]'::text[] = '{"string1","string2","string3"}'::text[]

这不起作用。所以我假设不,这种格式不能用于复制来自stdin。