【问题标题】:SQLAlchemy - NoReferencedTableError exception when accessing columns of alias of a reflected tableSQLAlchemy - 访问反射表的别名列时出现 NoReferencedTableError 异常
【发布时间】:2022-07-04 07:12:29
【问题描述】:

我在对从现有远程(即数据由第三方提供)数据库反映的表进行别名处理时遇到问题。

这是我的代码:

from sqlalchemy import create_engine
from sqlalchemy.engine import URL
engine = create_engine(URL.create(
    "mssql+pyodbc",
    ...
), future=True)
metadata = MetaData()
metadata.clear()
Store = Table('Store', metadata, autoload_with=engine, resolve_fks=False)
print(Store.c)

# Output:
ImmutableColumnCollection(Store.Id, Store.1CStatus, Store.CRMStatus, Store.ModifiedDate, Store.CRM_id, Store.1C_Id, Store.Name, Store.MainPriceList, Store.Adress, Store.PhoneNumber, Store.Driving, Store.Schedule, Store.Foto, Store.Stocks, Store.ERP_ID, Store.ERPStatus, Store.CheckoutMachine, Store.MainStock, Store.IsActive, Store.StoreFormat, Store.Parent_1CID, Store.LoadIStore, Store.Code)

我可以很好地连接和查询,但我需要自己加入这个表。我尝试为Store 表创建别名:

ParentStore = Table.alias()
print(ParentStore.c)

,但是访问c 集合会导致异常:

Traceback (most recent call last):
  File ".../script.py", line 257, in <module>
    print(get_data())
  File ".../script.py", line 132, in get_data
    print(ParentStore.c)
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/util/langhelpers.py", line 1113, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/sql/selectable.py", line 737, in columns
    self._populate_column_collection()
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/sql/selectable.py", line 1643, in _populate_column_collection
    self.element._generate_fromclause_column_proxies(self)
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/sql/selectable.py", line 694, in _generate_fromclause_column_proxies
    fromclause._columns._populate_separate_keys(
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/sql/base.py", line 1293, in _populate_separate_keys
    cols = list(iter_)
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/sql/selectable.py", line 695, in <genexpr>
    col._make_proxy(fromclause) for col in self.c
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/sql/schema.py", line 2037, in _make_proxy
    fk = [
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/sql/schema.py", line 2038, in <listcomp>
    ForeignKey(f.column, _constraint=f.constraint)
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/util/langhelpers.py", line 1113, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/sql/schema.py", line 2489, in column
    raise exc.NoReferencedTableError(
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'Store.MainPriceList' could not find table 'PriceListRegion' with which to generate a foreign key to target column 'Id'

我不知道为什么 SQLAlchemy 突然尝试解析 PriceListRegion 表,我不需要它。

更新: 不确定需要什么样的附加信息,但这里是metadata.tables 的内容,分配别名后:

FacadeDict({
    'Store': Table(
        'Store',
        MetaData(),
        Column('Id', INTEGER(), table=<Store>, primary_key=True, nullable=False, server_default=Identity(start=1, increment=1)),
        Column('1CStatus', INTEGER(), table=<Store>, nullable=False),
        Column('CRMStatus', INTEGER(), table=<Store>, nullable=False),
        Column('ModifiedDate', DATETIME(), table=<Store>, nullable=False),
        Column('CRM_id', NVARCHAR(length=36), table=<Store>, nullable=False),
        Column('1C_Id', CHAR(length=9, collation='Cyrillic_General_CI_AS'), table=<Store>, nullable=False),
        Column('Name', NVARCHAR(), table=<Store>, nullable=False),
        Column('MainPriceList', INTEGER(), ForeignKey('PriceListRegion.Id'), table=<Store>),
        Column('Adress', VARCHAR(length=150, collation='Cyrillic_General_CI_AS'), table=<Store>),
        Column('PhoneNumber', VARCHAR(length=50, collation='Cyrillic_General_CI_AS'), table=<Store>),
        Column('Driving', VARCHAR(length=80, collation='Cyrillic_General_CI_AS'), table=<Store>),
        Column('Schedule', VARCHAR(length=250, collation='Cyrillic_General_CI_AS'), table=<Store>),
        Column('Foto', VARCHAR(length=80, collation='Cyrillic_General_CI_AS'), table=<Store>),
        Column('Stocks', INTEGER(), table=<Store>),
        Column('ERP_ID', NVARCHAR(length=36), table=<Store>),
        Column('ERPStatus', INTEGER(), table=<Store>),
        Column('CheckoutMachine', INTEGER(), table=<Store>),
        Column('MainStock', INTEGER(), ForeignKey('Stocks.Id'), table=<Store>),
        Column('IsActive', INTEGER(), table=<Store>),
        Column('StoreFormat', INTEGER(), ForeignKey('StoreFormats.Id'), table=<Store>),
        Column('Parent_1CID', CHAR(length=9, collation='Cyrillic_General_CI_AS'), table=<Store>),
        Column('LoadIStore', INTEGER(), table=<Store>),
        Column('Code', INTEGER(), table=<Store>), schema=None
    )
})

【问题讨论】:

  • 没关系,任何具有外键约束的表都可以轻松重现它。显然,别名对象不“知道” fk 未解析并尝试访问外部表和错误,因为它不在元数据中。可能值得在 GitHub 上打开 discussion 以确定这是否是预期行为。

标签: python sqlalchemy


【解决方案1】:

根据snakecharmerb's suggestion,我在SQLAlchemy 的GitHub 上打开了discussion,并确认SQLAlchemy 试图解析别名表的外键约束确实是bug

【讨论】:

    猜你喜欢
    • 2014-08-16
    • 1970-01-01
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多