首页 文章

SqlAlchemy相当于使用FreeTDS的pyodbc连接字符串

提问于
浏览
22

以下作品:

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 :(错误)('08001','[08001] [unixODBC] [FreeTDS] [SQL Server]无法连接到数据源(0)(SQLDriverConnectW)')无无

有人可以指点我正确的方向吗?有没有办法告诉sqlalchemy将特定的连接字符串传递给pyodbc?

Please Note: 我想保持这个DSN-less .

5 回答

  • 30

    @Singletoned的例子不适用于SQLAlchemy 0.7.2 . 来自SQLAlchemy docs for connecting to SQL Server

    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
    
  • 18

    我仍然对在sqlalchemy create_engine 语句中的一行中执行此操作感兴趣,但我发现以下解决方法detailed here

    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)
    

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

    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))
    
  • 4

    这有效:

    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()
    
  • 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()
    
  • 0

    要将各种参数传递给connect函数,听起来像格式字符串可能会做你想要的:

    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

相关问题