【问题标题】:Mapping non-ascii, long column names in SQLAlchemy fails with NoSuchColumnError在 SQLAlchemy 中映射非 ascii 长列名失败并出现 NoSuchColumnError
【发布时间】:2014-07-24 22:09:22
【问题描述】:

会不会是 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'Levelez\xe9siC\xedmUtca': 'LevelezesiCimUtca',
            u'Szerz\u0151d\xe9sSorsz\xe1m': '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('Szerz\u0151d\xe9sSorsz\xe1m', INTEGER(), table=&lt;D_Allomanylista_Komplex_V&gt;, key='SzerzodesSzam', nullable=False),而对应的row.key()u'D_Allomanylista_Komplex_V_Szerz\u0151d\xe9sSorsz'。好像密钥会被截断(u'Szerz\u0151d\xe9sSorsz' 一次,u'Szerz\u0151d\xe9sSorsz\xe1m' 在另一点)。

查询row[u'D_Allomanylista_Komplex_V_Szerz\u0151d\xe9sSorsz'] 确实有效,并给出了预期的结果。

有没有办法避免这种截断?

【问题讨论】:

    标签: python sql-server sqlalchemy pyodbc


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      对我有用(即使在具有 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'Szerz\u0151d\xe9sSorsz\xe1m', 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]
      

      【讨论】:

      • 我认为您的示例和我的示例的主要区别在于我使用检查创建表,而您以声明方式构建它。因此,我将一个神秘构建的 Table 附加到我的声明性类中。错误不在连接Table和声明类,而是在Table和真正的mssql列之间。
      猜你喜欢
      • 1970-01-01
      • 2021-01-31
      • 2014-09-10
      • 2021-01-08
      • 1970-01-01
      • 2021-12-23
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多