我必须将数据从一个 postgreSQL 数据库(旧)传输到另一个 postgresSQL 数据库(新)。 旧的是在 win1252 中编码的。 New 以 utf-8 编码。
我已经尝试过不同的方法。 pandas.to_sql、sqlalchemy、psycopg2 等等,但由于编码“问题”而一直失败。我做了一些研究,最有效的事情看起来像是司机方面的问题。据我所知,psycopg2 使用 unicode 驱动程序,但使用我的源数据库版本(x86_64 上的 PostgreSQL 9.4.20)我必须使用 ANSI 来绕过这些编码问题。
我已经使用 ETL 工具测试了是否可以在没有编码问题的情况下导出受影响的表。没有问题是可能的。由于这个测试,我很确定这不是真正的编码问题,而是驱动程序处理问题。
当我只是用一个样本来测试加载数据是否正常工作时,我已经注意到 pandas 很慢。我必须加载 1.2 mio 记录。但这将永远运行。因此 postgreSQL 复制方法可能是首选方法。从我的角度来看,psycopg2 使用的是标准连接字符串 (https://halvar.at/python/odbc_dsn_connection_strings/)。但我必须使用 ANSI 驱动程序。
我试图将 SQLAlchemy 传递给你的 psycopg2 连接器。但这不起作用。
stage_engine_string = ("{PostgreSQL ANSI}+psycopg2://" + str(stage_user) + ":" + str(stage_password) + "@" + str(stage_host) + ":" + str(stage_port) + "/" + str(stage_database))
因为
conn = psycopg2.connect(**params)
只允许传递参数。
host =
database =
user =
password =
port =
在我尝试上述之前,我尝试了 ex.
cur.copy_to(open("sql_tmp_export.csv", "w", encoding="utf-8", errors="ignore"), "table", sep=";", columns=("no","description"))
,
conn.decode("win1250").encode("utf8")
和
conn.set_client_encoding("win1250")
但我一直收到一个encoidng问题。基于 utf8 和 win1250 之间切换的 postgres 文档应该永远不会有问题。
在 ETL 工具上,我遇到了类似的问题,但能够通过发送 an 解决它
"set client_encoding=\"windows-1250\"
在建立与数据库的连接之后。
但是如果我在 psycopg2 中尝试这个
cur.execute("set client_encoding=\"windows-1250\;select * from table")
我仍然遇到编码问题。
如果我可以选择通过驱动程序建立 psycopg2 连接,有什么线索吗?我认为这应该可以解决我的问题。
我真正的问题(从数据库中获取数据)因为跟进问题没有得到解决。如果您想进入,我很乐意讨论我的下一个问题:使用 Python 从远程服务器下载 postgreSQL pg_dump 文件
但是我能够解决这个问题。如果你想使用 ANSI,你必须从 https://www.postgresql.org/ftp/odbc/versions/msi/
安装最后一个 ODBC 驱动程序然后您可以将 psycopg2 连接切换到 pyodbc 连接。
import pyodbc
conn_str = (
"DRIVER={PostgreSQL Ansi(x64)};"
"DATABASE="+database+";"
"UID="+user+";"
"PWD="+password+";"
"SERVER="+host+";"
"PORT="+port+";"
)
conn = pyodbc.connect(conn_str)
cur = conn.execute("SELECT 1")
row = cur.fetchone()
print(row)
cur.close()
conn.close()
我的一般问题现在也已解决。但是解决方案很奇怪。如果有人卡在类似的东西上,我只需运行相同的脚本两次,但首先运行限制和偏移量。
def any_postrgres_method_to_load_data_from_db:
conn = some_lib.conect(var1, var2)
cur = conn.cursor()
sql_pre_statement = """\
set client_encoding = "Windows-1250"
"""
cur.execute(sql_pre_statement)
sql_statement = """\
select * from n
"""
cur.execute(sql_statement)
df = pandas.read_sql_query(sql, conn)
df.to_csv("sql_tmp_export.csv", index=False)
上面的脚本返回了几个编码问题。 运行如下所示略微调整的脚本后,我能够运行原来的脚本。
def any_postrgres_method_to_load_data_from_db:
conn = some_lib.conect(var1, var2)
cur = conn.cursor()
sql_pre_statement = """\
set client_encoding = "Windows-1250"
"""
cur.execute(sql_pre_statement)
sql_statement = """\
select * from n offset 500 limit 1000
"""
cur.execute(sql_statement)
df = pandas.read_sql_query(sql, conn)
df.to_csv("sql_tmp_export.csv", index=False)
我真的无法解释这个。我只是觉得远程数据库的缓存中有一些奇怪的东西。