我必须从几个不同的数据库引擎中提取数据。导出此数据后,我将数据发送到 AWS S3 并使用 COPY 命令将该数据复制到 Redshift。一些表格包含大量文本,列字段中存在换行符和其他字符。当我运行以下代码时:
cursor.execute('''SELECT * FROM some_schema.some_message_log''')
rows = cursor.fetchall()
with open('data.csv', 'w', newline='') as fp:
a = csv.writer(fp, delimiter='|', quoting=csv.QUOTE_ALL, quotechar='"', doublequote=True, lineterminator='\n')
a.writerows(rows)
一些具有回车符/换行符的列将创建新行:
"2017-01-05 17:06:32.802700"|"SampleJob"|""|"Date"|"error"|"Job.py"|"syntax error at or near ""from"" LINE 34: select *, SYSDATE, from staging_tops.tkabsences;
^
-<class 'psycopg2.ProgrammingError'>"
导致导入过程失败。我可以通过对异常进行硬编码来解决这个问题:
cursor.execute('''SELECT * FROM some_schema.some_message_log''')
rows = cursor.fetchall()
with open('data.csv', 'w', newline='') as fp:
a = csv.writer(fp, delimiter='|', quoting=csv.QUOTE_ALL, quotechar='"', doublequote=True, lineterminator='\n')
for row in rows:
list_of_rows = []
for c in row:
if isinstance(c, str):
c = c.replace("\n", "\\n")
c = c.replace("|", "\|")
c = c.replace("\\", "\\\\")
list_of_rows.append(c)
else:
list_of_rows.append(c)
a.writerow([x.encode('utf-8') if isinstance(x, str) else x for x in list_of_rows])
但这需要很长时间来处理较大的文件,并且通常看起来是不好的做法。有没有更快的方法将数据从 SQL 游标导出到 CSV,当遇到包含回车符/换行符的文本列时不会中断?
最佳答案
如果您在执行 SELECT * FROM table
时没有使用 WHERE
子句,则可以使用 COPY table TO STDOUT
选项:
copy_command = """COPY some_schema.some_message_log TO STDOUT
CSV QUOTE '"' DELIMITER '|' FORCE QUOTE *"""
with open('data.csv', 'w', newline='') as fp:
cursor.copy_expert(copy_command)
在我的测试中,这会导致文字“\n”而不是实际的换行符,其中通过 csv 编写器写入会给出虚线。
如果您在生产中确实需要 WHERE
子句,您可以创建一个临时表并复制它:
cursor.execute("""CREATE TEMPORARY TABLE copy_me AS
SELECT this, that, the_other FROM table_name WHERE conditions""")
(编辑)再次查看您的问题,我看到您提到“所有不同的数据库引擎”。以上适用于 psyopg2 和 postgresql,但可能适用于其他数据库或库。
关于python - 将 SQL 查询的结果写入 CSV 并避免额外的换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48793896/