使用 psycopg2 将多行插入 postgreSQL 时出错

tan*_*bog 3 python postgresql psycopg2 xml-parsing python-3.x

我需要打开许多 XML 文件,然后进行处理以生成大量行,然后将这些行插入到远程 Postgress 数据库中的多个表中。

为了提取 XML 数据,我使用它xml.etree.ElementTree来解析 XML 树并根据需要提取元素。当我做很多事情时,基本操作是获取特定元素(无论是字符串还是整数)并将其放入多个字典之一中。

经过更多处理后,我需要将许多字典插入到数据库中。对于任何单个 xml 文件,我可能会在 3 个表中生成最多 8-10,000 行(或查询)。

在测试时,我输出到 sql 文件,然后手动运行查询。如果我有很多 xml 文件,这显然是行不通的。

因此,我尝试使用psycopg2自动化这个过程。据我了解,从堆栈溢出和其他地方运行单个execute 函数的速度非常慢。基于此 stackoverflow 问题,我尝试编写如下代码:

QueryData = ','.join(cur.mogrify('(%s,%s,%s)', row) for row in myData)
cur.execute('INSERT INTO DBTABLE' + QueryData)
cur.commit()
Run Code Online (Sandbox Code Playgroud)

其中myData是一个元组列表[(a,b,c),(a,b,c),(a,b,c)...],其内容是由我提取的数据xml.etree.ElementTree和我自己计算的值的组合。

当我尝试实际执行上面的代码时,我收到以下错误:

TypeError: sequence item 0: expected str instance, bytes found

好的...如果我然后尝试将我的数据(每个元组元素)转换为str()我得到的结果:

TypeError: encoding without a string argument
Run Code Online (Sandbox Code Playgroud)

我的做法是完全错误的吗?我怎样才能做我需要的事情?我正在使用Python3。

额外的

我被要求展示一个数据示例。

这是最简单的,将 3 个整数值放入一个表中。它的形式如下:(document_id,item_index,item_code)

一个典型的例子是:(937, 138, 681)

我一般的转换尝试是尝试:

(str(document_id),str(item_index),str(item_code))
Run Code Online (Sandbox Code Playgroud)

我也尝试过另一种方式:

(bytes(document_id,'utf-8'),bytes(item_index,'utf-8'),bytes(item_code,'utf-8'))
Run Code Online (Sandbox Code Playgroud)

后者也会引发错误:TypeError: encoding without a string argument

Aga*_*ara 7

psycopg文档指出对于 cur.mogrify:

返回的字符串始终是字节字符串。

因此,要使用此 hack,您只需将 mogrify 的结果解码回字符串,例如:

QueryData = ','.join(cur.mogrify('(%s,%s,%s)', row).decode('utf-8') for row in myData)
cur.execute('INSERT INTO DBTABLE' + QueryData)
Run Code Online (Sandbox Code Playgroud)

然而,正如StackOverflow 问题中提到的,复制大量数据的最有效方法是使用COPY。您可以使用任何“类似 python 文件的对象”来执行此操作。这是 psycopg 文档中的一个示例:

>>> f = StringIO("42\tfoo\n74\tbar\n")
>>> cur.copy_from(f, 'test', columns=('num', 'data'))
>>> cur.execute("select * from test where id > 5;")
>>> cur.fetchall()
[(6, 42, 'foo'), (7, 74, 'bar')]
Run Code Online (Sandbox Code Playgroud)