SqlAlchemy 正确创建引擎 URL 的方法

0 投票
1 回答
39 浏览
提问于 2025-04-14 15:46

创建一个需要传递给 sqlalchemy.create_engineurl,最好的方法是什么? https://docs.sqlalchemy.org/en/20/core/engines.html#sqlalchemy.create_engine

我的连接字符串大概是这样的:

con_str = "Driver={ODBC Driver 17 for SQL Server};Server=tcp:somedb.database.windows.net,1433;Database=somedbname;Uid=someuser;Pwd=some++pass=;Encrypt=yes;TrustServerCertificate=no"

如果我这样做(使用 sqlalchemy 和 pyodbc 连接到 SQL Server 2012):

import urllib

import sqlalchemy as sa


connection_url = sa.engine.URL.create(
    "mssql+pyodbc",
    query={"odbc_connect": urllib.parse.quote_plus(con_str)},
)

print(connection_url.render_as_string(hide_password=False))

我得到的结果是:

mssql+pyodbc://?odbc_connect=Driver%3D%7BODBC+Driver+17+for+SQL+Server%7D%3BServer%3Dtcp%3Asomedb.database.windows.net%2C1433%3BDatabase%3Dsomedbname%3BUid%3Dsomeuser%3BPwd%3Dsome%2B%2Bpass%3D%3BEncrypt%3Dyes%3BTrustServerCertificate%3Dno

但是如果我这样做(如何使用包含 @ 的密码来调用 SQLAlchemy 的 create_engine()?):

connection_url = sa.engine.URL.create(
    drivername="mssql+pyodbc",
    username="someuser",
    password="some++pass=",
    host="tcp:somedb.database.windows.net",
    port=1433,
    database="somedbname",
    query={'driver': 'ODBC Driver 17 for SQL Server', 'encrypt': 'yes', 'trustservercertificate': 'no'},
)

print(connection_url.render_as_string(hide_password=False))

我得到的结果就不一样了:

mssql+pyodbc://someuser:some++pass%3D@[tcp:somedb.database.windows.net]:1433/somedbname?driver=ODBC+Driver+17+for+SQL+Server&encrypt=yes&trustservercertificate=no

这两种方法在一般的读取操作中都能用,但在一些特殊情况下它们的结果却不同

举个例子,对于某段代码,前一种方法可以正常工作,而后一种方法则会抛出错误:

('42000', '[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]隐式转换从数据类型 nvarchar(max) 到 binary 是不允许的。请使用 CONVERT 函数来运行此查询。 (257) (SQLExecDirectW)').

我认为前一种方法是正确的,因为大多数 StackOverflow 的回答都把它作为示例。我想知道为什么不同的参数会产生如此不同的结果,以及我可以在哪里阅读相关内容,网址是 https://docs.sqlalchemy.org/

1 个回答

0

我不使用这个数据库或驱动,但文档里有一些关于你提到的两个例子的资料。看起来这两个都是被支持的。

pass-through-exact-pyodbc-string

  • 文档里没有使用 urllib.parse.quote_plus,或许你可以试试不使用这个?也许会回退到其他驱动?

hostname-connections

  • 他们的 "trustservercertificate" 写成了 "TrustServerCertificate",这可能没关系,因为文档里只提到 "driver" 是特别的。

撰写回答