在SQLAlchemy中映射非ascii的长列名失败,返回NoSuchColumnError



可能是RowProxy对象的键被截断到一定长度吗?

我有一个遗留的MSSQL数据库,其中有一些列名带有重音字母。

我用下面的代码映射它的列到python属性:

@event.listens_for(Table, "column_reflect")
def column_reflect(inspector, table, column_info):
    if table.name == 'D_Allomanylista_Komplex_V':
        # set column.key = "attr_<lower_case_name>"
        columns_to_change = {
            'Allapot': 'allapot',
            'BIZTNEVE': 'biztosito_neve',
            u'Levelezxe9siCxedmUtca': 'LevelezesiCimUtca',
            u'Szerzu0151dxe9sSorszxe1m': 'SzerzodesSzam',
        }
        column_info['key'] = columns_to_change.get(column_info['name'], column_info['name'])
komplex_table = inspect_komplex_table()
class BiztositasokModel(Base):
    __table__ = komplex_table
    __mapper_args__ = {
        'primary_key': [
            komplex_table.c[u'KTVSZAM'],
            komplex_table.c[u'NyugtaSzam'],
            komplex_table.c[u'ajanlatszam'],
            komplex_table.c['SzerzodesSzam'],
            ],
        'include_properties': [
            'biztosito_neve',
            komplex_table.c['allapot'],
            komplex_table.c['LevelezesiCimUtca'],
            komplex_table.c['SzerzodesSzam'],
            'KTVSZAM', 'NyugtaSzam', 'ajanlatszam'],
    }

不幸的是,当我尝试查询时,这段代码给出了一个错误,指出SzerzodesSzam列不存在。

/Users/viktornagy/.virtualenvs/dosszie/lib/python2.7/site-packages/sqlalchemy/orm/loading.pyc in _instance(row, result)
    361             identitykey = (
    362                 identity_class,
--> 363                 tuple([row[column] for column in pk_cols])
    364             )
    365
/Users/viktornagy/.virtualenvs/dosszie/lib/python2.7/site-packages/sqlalchemy/engine/result.pyc in _key_fallback(self, key, raiseerr)
    329                 raise exc.NoSuchColumnError(
    330                     "Could not locate column in row for column '%s'" %
--> 331                     expression._string_or_unprintable(key))
    332             else:
    333                 return None
NoSuchColumnError: "Could not locate column in row for column 'D_Allomanylista_Komplex_V.Szerz\u0151d\xe9sSorsz\xe1m'"

我进入调试模式寻找问题的根源,发现在363行上面的列是Column('Szerzu0151dxe9sSorszxe1m', INTEGER(), table=<D_Allomanylista_Komplex_V>, key='SzerzodesSzam', nullable=False),而对应的row.key()u'D_Allomanylista_Komplex_V_Szerzu0151dxe9sSorsz'。就好像键会被截断(u'Szerzu0151dxe9sSorsz'一次,u'Szerzu0151dxe9sSorszxe1m'另一次)。

查询row[u'D_Allomanylista_Komplex_V_Szerzu0151dxe9sSorsz']确实有效,并且给出了预期的结果。

是否有办法避免这种截断?

以上似乎是pyodbc驱动程序的限制。切换到pymssql解决了这个问题。

适合我(即使在使用freetds 0.86的OSX上,通常这是unicode DDL严重失败的地方):

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Foo(Base):
    __tablename__ = 'D_Allomanylista_Komplex_V'
    bar = Column(u'Szerzu0151dxe9sSorszxe1m', INTEGER(), autoincrement=False, primary_key=True)
e = create_engine("mssql+pyodbc://scott:tiger@ms_2008", echo=True)
c = e.connect()
t = c.begin()
Base.metadata.create_all(c)
s = Session(c)
s.add(Foo(bar=5))
s.commit()
row = s.query(Foo).first()
assert row.bar == 5
输出:

CREATE TABLE [D_Allomanylista_Komplex_V] (
    [SzerződésSorszám] INTEGER NOT NULL, 
    PRIMARY KEY ([SzerződésSorszám])
)
2014-07-24 19:15:22,504 INFO sqlalchemy.engine.base.Engine ()
2014-07-24 19:15:22,507 INFO sqlalchemy.engine.base.Engine INSERT INTO [D_Allomanylista_Komplex_V] ([SzerződésSorszám]) VALUES (?)
2014-07-24 19:15:22,507 INFO sqlalchemy.engine.base.Engine (5,)
2014-07-24 19:15:22,510 INFO sqlalchemy.engine.base.Engine SELECT TOP 1 [D_Allomanylista_Komplex_V].[SzerződésSorszám] AS [D_Allomanylista_Komplex_V_SzerződésSorszám] 
FROM [D_Allomanylista_Komplex_V]

最新更新