我有一个包含文本数组(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']"
答案 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。