27

以下作品:

import pyodbc
pyodbc.connect('DRIVER={FreeTDS};Server=my.db.server;Database=mydb;UID=myuser;PWD=mypwd;TDS_Version=8.0;Port=1433;')

以下失败:

import sqlalchemy
sqlalchemy.create_engine("mssql://myuser:mypwd@my.db.server:1433/mydb?driver=FreeTDS& odbc_options='TDS_Version=8.0'").connect()

上面的错误信息是:

DBAPIError: (Error) ('08001', '[08001] [unixODBC][FreeTDS][SQL Server]无法连接到数据源 (0) (SQLDriverConnectW)') 无 无

有人可以指出我正确的方向吗?有没有一种方法可以简单地告诉 sqlalchemy 将特定的连接字符串传递给 pyodbc?

请注意:我想保留这个 DSN-less。

4

5 回答 5

43

@Singletoned 的示例不适用于 SQLAlchemy 0.7.2。从用于连接到 SQL Server 的 SQLAlchemy 文档

If you require a connection string that is outside the options presented above, use the odbc_connect keyword to pass in a urlencoded connection string. What gets passed in will be urldecoded and passed directly.

所以为了让它工作,我使用了:

import urllib
quoted = urllib.quote_plus('DRIVER={FreeTDS};Server=my.db.server;Database=mydb;UID=myuser;PWD=mypwd;TDS_Version=8.0;Port=1433;')
sqlalchemy.create_engine('mssql+pyodbc:///?odbc_connect={}'.format(quoted))

这也应该适用于 Sybase。

注意:在 python 3 中,urllib 模块已被拆分为多个部分并重命名。因此,python 2.7 中的这一行:

quoted = urllib.quote_plus

必须在python3中更改为这一行:

quoted = urllib.parse.quote_plus
于 2011-09-13T09:27:09.810 回答
24

我仍然对在 sqlalchemy 语句中的一行中执行此操作的方法感兴趣,但我在这里create_engine找到了以下解决方法:

import pyodbc, sqlalchemy

def connect():
    pyodbc.connect('DRIVER={FreeTDS};Server=my.db.server;Database=mydb;UID=myuser;PWD=mypwd;TDS_Version=8.0;Port=1433;')

sqlalchemy.create_engine('mssql://', creator=connect)

更新:解决了我在自己的评论中提出的关于无法将参数传递给连接字符串的问题。如果您需要在运行时动态连接到不同的数据库,以下是一个通用的解决方案。我只将数据库名称作为参数传递,但可以根据需要轻松使用其他参数:

import pyodbc
import os

class Creator:
    def __init__(self, db_name='MyDB'):
        """Initialization procedure to receive the database name"""
        self.db_name = db_name

    def __call__(self):
        """Defines a custom creator to be passed to sqlalchemy.create_engine
           http://stackoverflow.com/questions/111234/what-is-a-callable-in-python#111255"""
        if os.name == 'posix':
            return pyodbc.connect('DRIVER={FreeTDS};'
                                  'Server=my.db.server;'
                                  'Database=%s;'
                                  'UID=myuser;'
                                  'PWD=mypassword;'
                                  'TDS_Version=8.0;'
                                  'Port=1433;' % self.db_name)
        elif os.name == 'nt':
            # use development environment
            return pyodbc.connect('DRIVER={SQL Server};'
                                  'Server=127.0.0.1;'
                                  'Database=%s_Dev;'
                                  'UID=user;'
                                  'PWD=;'
                                  'Trusted_Connection=Yes;'
                                  'Port=1433;' % self.db_name)

def en(db_name):
    """Returns a sql_alchemy engine"""
    return sqlalchemy.create_engine('mssql://', creator=Creator(db_name))
于 2010-12-20T20:43:34.393 回答
5

在内部,“my.db.server:1433”作为连接字符串的一部分传递,例如SERVER=my.db.server:1433;.

不幸的是 unixODBC/FreeTDS 不接受 SERVER 位中的端口。相反,它想要SERVER=my.db.server;PORT=1433;

要将 sqlalchemy 语法用于连接字符串,您必须将端口指定为参数。

sqlalchemy.create_engine("mssql://myuser:mypwd@my.db.server:1433/mydb?driver=FreeTDS& odbc_options='TDS_Version=8.0'").connect()

变成:

sqlalchemy.create_engine("mssql://myuser:mypwd@my.db.server/mydb?driver=FreeTDS&port=1433& odbc_options='TDS_Version=8.0'").connect()
于 2013-10-19T19:08:37.577 回答
5

这有效:

import sqlalchemy
sqlalchemy.create_engine("DRIVER={FreeTDS};Server=my.db.server;Database=mydb;UID=myuser;PWD=mypwd;TDS_Version=8.0;Port=1433;").connect()

在这种格式中,SQLAlchemy 只是忽略连接字符串并将其直接传递给 pyodbc。

更新:

抱歉,我忘记了 uri 必须是 url 编码的,因此,以下工作:

import sqlalchemy
sqlalchemy.create_engine("DRIVER%3D%7BFreeTDS%7D%3BServer%3Dmy.db.server%3BDatabase%3Dmydb%3BUID%3Dmyuser%3BPWD%3Dmypwd%3BTDS_Version%3D8.0%3BPort%3D1433%3B").connect()
于 2011-02-26T21:41:36.477 回答
0

要将各种参数传递给您的连接函数,听起来格式字符串可能会执行您想要的操作:

def connect(server, dbname, user, pass):
  pyodbc.connect('DRIVER={FreeTDS};Server=%s;Database=%s;UID=%s;PWD=%s;TDS_Version=8.0;Port=1433;' % (server, dbname, user, pass))

然后你会用类似的东西来调用它:

connect('myserver', 'mydatabase', 'myuser', 'mypass')

有关格式字符串的更多信息在这里:http ://docs.python.org/library/string.html#formatstrings

于 2010-12-22T01:44:07.017 回答