我有两个postgres数据库,它们的模式相同,但模式不同。我正在编写一个python脚本,目标是从其中一个表中导出部分数据,然后将结果导入到不同数据库中的同一个表中(如select from A where f=123
)。架构很大(它有很多不同类型的列,有的允许空,有的不允许空,有日期类型,有字符串字段,可以包含句子,伪查询和文件名),并且在表中可以有数千行。
我采取的方法是将数据从表导出到csv文件,然后将数据从csv文件导入到第二个数据库表。
我使用psycopg2
lib在Python中处理Postgres沿着使用csv
lib读写csv文件。
我实现了第一个版本。问题是:行中的某些列为空,当我在python中读取表数据时,空字段具有None
值,当字段被允许为null
时,并且当字段不被允许为null
时,值为""
空字符串,并且当导出到csv时,所有值None
和""
作为空字符串插入到csv文件中。例如,该行看起来像1234,,,,,1,,
。当我试图将文件导入到postgres表中时,csv中的所有空值都被转换为null
,并试图以这种方式插入。但是它失败了,因为不能是null
的字段不接受这个值。下面你可以看到我的代码和代码后,我粘贴的改进,我没有避免这个问题。
import psycopg2
import csv
def export_table(filename, tablename):
conn = psycopg2.connect(....)
cur = conn.cursor()
cur.execute(f'SELECT * FROM {tablename} where f=123')
rows = cur.fetchall()
with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
for row in rows:
writer.writerow(row)
cur.close()
conn.close()
def import_table(filename, tablename):
conn = psycopg2.connect(..second db data)
cur = conn.cursor()
with open(filename, 'r') as csvfile:
cur.copy_expert(
f"COPY {tablename} FROM STDIN WITH (FORMAT CSV)",
csvfile
)
conn.commit()
cur.close()
conn.close()
我尝试添加csv.QUOTE_MINIMAL
、csv.QUOTE_NONNUMERIC
-它们没有帮助我。
因为我无法用这段代码导入数据,所以我尝试再做一件事。
我添加了一个手动引用功能:
def quote_field(field):
if isinstance(field, str):
if field == '':
return '""'
elif any(c in field for c in (',', '"', '\n')):
return '"' + field.replace('"', '""') + '"'
return field
并以如下方式更新了导入部件:
with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, quoting=csv.QUOTE_NONE, quotechar='', escapechar='\\')
for row in rows:
writer.writerow([quote_field(field) for field in row])
我试着运行这段代码,它将空值粘贴到csv中作为""
,而None
值则作为空字段放置在csv中。因此,csv中的一行将看起来像1234,,,"","",,,,,"",,,,,
,在某些情况下,这将成功地工作。数据导入正确。2但是有时由于某些原因,生成的csv文件根本没有导入或者只是部分导入。为了检查它,我尝试使用DataGrip从csv文件手动导入数据,对于某些数据,它也只是部分导入(比如1000行中有20行),有些数据根本没有导入。我检查了csv的有效性,他们是有效的。我认为有一个错误在一个导入部分,但我不知道它在哪里,为什么它是这样的行为。需要帮助。
1条答案
按热度按时间zkure5ic1#
创建表格:
Python代码:
在psql中:
cur.copy_expert('copy (select * from csv_null ) TO STDOUT WITH CSV HEADER', buffer)
将产生cur.copy_expert('copy csv_null_2 from STDIN WITH CSV HEADER', buffer)
将正确使用的输出,而不是从一个上下文Pythoncsv
跳到PostgresCOPY
。更新
修改表格以包含
NOT NULL
列:Python代码:
在
psql
中: