使用 ANSI driver 通过 python psycopg2 连接到 postgreSQL 数据库

Useing ANSI driver to connect to a postgreSQL DB with python psycopg2

我必须将数据从一个 postgreSQL 数据库(旧)传输到另一个 postgresSQL 数据库(新)。 旧的是在 win1252 中编码的。新的以 utf-8 编码。

我已经尝试过不同的方法。 pandas.to_sql、sqlalchemy、psycopg2 等等,但由于编码“问题”而一直失败。我做了一些研究,最有效的事情看起来像是 driver 方面的问题。据我所知,psycopg2 使用 unicode driver 但我的源数据库版本(x86_64 上的 PostgreSQL 9.4.20)我必须使用 ANSI 来绕过这些编码问题。

我已经使用 ETL 工具测试了是否可以在没有编码问题的情况下导出受影响的 table。没有问题是可能的。由于这个测试,我很确定这不是真正的编码问题,而不是 driver 处理问题。

当我刚刚使用示例来测试加载数据是否正常时,我已经注意到 pandas 速度很慢。我必须加载 1.2 mio 记录。但这将永远运行。因此 postgreSQL 复制方法可能是首选方法。从我的角度来看,psycopg2 使用的是标准连接字符串 (https://halvar.at/python/odbc_dsn_connection_strings/)。但我必须使用 ANSI driver.

我试图将 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")

但我一直收到编码问题。基于 utf8 和 win1250 之间切换的 postgres 文档应该永远不会有问题。

在 ETL 工具上,我遇到了类似的问题,但能够通过发送

"set client_encoding=\"windows-1250\"

建立与数据库的连接后。

但是如果我在 psycopg2 中尝试这个

cur.execute("set client_encoding=\"windows-1250\;select * from table")

我仍然遇到编码问题。

如果我可以选择通过 driver 建立 psycopg2 连接,有什么线索吗?我认为这应该可以解决我的问题。

我真正的问题(从数据库中获取数据)由于后续问题没有得到解决。如果您想进入,我很乐意讨论我的下一个问题:Downloading a postgreSQL pg_dump file from a remote server using Python

但我能够解决这个问题。如果你想使用 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)

我真的无法解释这个。我只是觉得远程数据库的缓存中有一些奇怪的东西。