mssql db 和 sqlalchemy 中表/列的 Unicode 名称

Posted

技术标签:

【中文标题】mssql db 和 sqlalchemy 中表/列的 Unicode 名称【英文标题】:Unicode names of tables/columns in mssql db and sqlalchemy 【发布时间】:2014-04-17 12:10:14 【问题描述】:

我正在使用来自 pip 的最新 sqlalchemy 和最新 pymssql 来连接 mssql 服务器 8.00.2039(2005 年?),困难在于表名和列名是俄语。是否可以用 sqlalchemy 处理这个数据库?至少我必须进行“选择...在哪里”查询。

engine = create_engine("mssql+pymssql://%s:%s@RTBD/rt?charset=utf8" % (settings.RT_USER, settings.RT_PWD), echo = True, encoding = 'utf8')
metadata = MetaData()
metadata.reflect(engine, only = [u"Заказы",])
orders = metadata.tables[u'Заказы']
res = engine.execute(orders.select(orders.c[u'Номер заказа'] == u'14-01-0001'))

例外是

ValueError                                Traceback (most recent call last)
<ipython-input-8-50ce93243d1c> in <module>()
----> 1 engine.execute(orders.select(orders.c[orders.columns.keys()[0]] == u'14-01-0001'))

python2.7/site-packages/sqlalchemy/engine/base.pyc in execute(self, statement, *multiparams, **params)
   1680 
   1681         connection = self.contextual_connect(close_with_result=True)
-> 1682         return connection.execute(statement, *multiparams, **params)
   1683 
   1684     def scalar(self, statement, *multiparams, **params):

python2.7/site-packages/sqlalchemy/engine/base.pyc in execute(self, object, *multiparams, **params)
    718                                 type(object))
    719         else:
--> 720             return meth(self, multiparams, params)
    721 
    722     def _execute_function(self, func, multiparams, params):

python2.7/site-packages/sqlalchemy/sql/elements.pyc in _execute_on_connection(self, connection, multiparams, params)
    315 
    316     def _execute_on_connection(self, connection, multiparams, params):
--> 317         return connection._execute_clauseelement(self, multiparams, params)
    318 
    319     def unique_params(self, *optionaldict, **kwargs):

python2.7/site-packages/sqlalchemy/engine/base.pyc in _execute_clauseelement(self, elem, multiparams, params)
    815             compiled_sql,
    816             distilled_params,
--> 817             compiled_sql, distilled_params
    818         )
    819         if self._has_events or self.engine._has_events:

python2.7/site-packages/sqlalchemy/engine/base.pyc in _execute_context(self, dialect, constructor, statement, parameters, *args)
    945                                 parameters,
    946                                 cursor,
--> 947                                 context)
    948 
    949         if self._has_events or self.engine._has_events:

python2.7/site-packages/sqlalchemy/engine/base.pyc in _handle_dbapi_exception(self, e, statement, parameters, cursor, context)
   1109                                 )
   1110 
-> 1111             util.reraise(*exc_info)
   1112 
   1113         finally:

python2.7/site-packages/sqlalchemy/engine/base.pyc in _execute_context(self, dialect, constructor, statement, parameters, *args)
    938                                      statement,
    939                                      parameters,
--> 940                                      context)
    941         except Exception as e:
    942             self._handle_dbapi_exception(

python2.7/site-packages/sqlalchemy/engine/default.pyc in do_execute(self, cursor, statement, parameters, context)
    433 
    434     def do_execute(self, cursor, statement, parameters, context=None):
--> 435         cursor.execute(statement, parameters)
    436 
    437     def do_execute_no_params(self, cursor, statement, context=None):

python2.7/site-packages/pymssql.so in pymssql.Cursor.execute (pymssql.c:6057)()

python2.7/site-packages/_mssql.so in _mssql.MSSQLConnection.execute_query (_mssql.c:9858)()

python2.7/site-packages/_mssql.so in _mssql.MSSQLConnection.execute_query (_mssql.c:9734)()

python2.7/site-packages/_mssql.so in _mssql.MSSQLConnection.format_and_run_query (_mssql.c:10814)()

python2.7/site-packages/_mssql.so in _mssql.MSSQLConnection.format_sql_command (_mssql.c:11042)()

python2.7/site-packages/_mssql.so in _mssql._substitute_params (_mssql.c:18359)()

<type 'str'>: (<type 'exceptions.UnicodeEncodeError'>, UnicodeEncodeError('ascii', u'params dictionary did not contain value for placeholder: \u041d\u043e\u043c\u0435\u0440 \u0437\u0430\u043a\u0430\u0437\u0430_1', 57, 62, 'ordinal not in range(128)'))

查询正确,以WHERE [Заказы].[Номер заказа] = %(Номер заказа_1)s结尾

但是来自 sqla 的信息是INFO sqlalchemy.engine.base.Engine '\xd0\x9d\xd0\xbe\xd0\xbc\xd0\xb5\xd1\x80 \xd0\xb7\xd0\xb0\xd0\xba\xd0\xb0\xd0\xb7\xd0\xb0_1': '14-01-0001'

字符串\xd0\x9d\xd0\xbe\xd0\xbc\xd0\xb5\xd1\x80 \xd0\xb7\xd0\xb0\xd0\xba\xd0\xb0\xd0\xb7\xd0\xb0_1\u041d\u043e\u043c\u0435\u0440 \u0437\u0430\u043a\u0430\u0437\u0430_1 等于Номер заказа_1

【问题讨论】:

【参考方案1】:

如邮件列表中所述,FreeTDS 等对此非常挑剔。以下测试适用于我,但对于上面的海报它不起作用:

    UnixODBC 2.3.0 FreeTDS 0.91 Pyodbc 3.0.7 Linux,而不是 OSX,OSX 的 tds / pyodbc 有很多问题,我在这里运行在 Fedora 14 机器上

Freetds 设置:

[sqlserver_2008_vmware]
        host = 172.16.248.142
        port = 1213
        tds version = 7.2
        client charset = UTF8
        text size = 50000000

测试脚本:

# coding: utf-8
from sqlalchemy import create_engine, MetaData, Table, Column, String

e = create_engine("mssql+pyodbc://scott:tiger@ms_2008", echo=True)
#e = create_engine("mssql+pymssql://scott:tiger@172.16.248.142:1213", echo=True)

m = MetaData()

t = Table(u'Заказы', m, Column(u'Номер заказа', String(50)))

m.drop_all(e)
m.create_all(e)

orders = m.tables[u'Заказы']
e.execute(orders.select(orders.c[u'Номер заказа'] == u'14-01-0001'))

部分输出:

CREATE TABLE [Заказы] (
    [Номер заказа] VARCHAR(50) NULL
)


2014-03-31 20:57:16,266 INFO sqlalchemy.engine.base.Engine ()
2014-03-31 20:57:16,268 INFO sqlalchemy.engine.base.Engine COMMIT
2014-03-31 20:57:16,270 INFO sqlalchemy.engine.base.Engine SELECT [Заказы].[Номер заказа] 
FROM [Заказы] 
WHERE [Заказы].[Номер заказа] = ?
2014-03-31 20:57:16,270 INFO sqlalchemy.engine.base.Engine (u'14-01-0001',)

【讨论】:

以上是关于mssql db 和 sqlalchemy 中表/列的 Unicode 名称的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy 无法连接到 mssql 数据库

SQLAlchemy中表结构的一对多

使用 sqlalchemy 连接到 mssql 数据库时遇到问题

使用sqlalchemy连接mssql

使用 Flask-SQLAlchemy 连接到 MSSQL 数据库

使用 sqlalchemy.engine.url.URL 为 mssql+pyodbc 构建连接 URL