例如,假设我有一个视图
create view MyView as select 1 as A, 2 as B
(上面的SQL是微软方言,但视图本身的细节并不重要。)
我将此视图包装在我的 SQLAlchemy 模型定义中:
class MyView(Base):
__tablename__ = 'MyView'
A = Column(Integer)
B = Column(Integer)
该视图不仅在 SQLAlchemy 中使用。 其他应用程序或手写的 SQL 查询可能会使用它。 假设我想向视图添加一个新列,所以它现在显示为
create view MyView as select 1 as A, 2 as B, 3 as C
(这个新版本的视图对于大多数应用程序查询向后兼容。只有使用
select *
的查询才会看到不同的结果。将视图与其他视图或表连接的查询也提供名为 C
的列,但不完全限定列名,可能会出现有关不明确列名的错误。)
假设目前我不打算使用 SQLAlchemy 中的列
C
并且我不将其添加到模型定义中。 我最终可能会这样做,但无论出于何种原因,我现在还不能更改代码,或者至少不能发布新版本。 将列添加到视图并保持与现有 SQLAlchemy 模型文件兼容是否安全?
因为我询问的是视图,而不是表,所以请假设 SQLAlchemy 仅提供读取访问权限。 应用程序不会尝试更新视图或从视图中删除,即使这在某些 RDBMS 中是可能的。
如果 SQLAlchemy 尝试内省视图中的列并抱怨模型中未提及的其他列,那么不会有任何问题吗? 我认为不是......但我还没有找到明确的答案。
这应该没问题,只要您在映射中的视图中显式定义所需的列即可。 所以这个(你说你正在使用的)很好
class MyModel(Base):
__tablename__ = 'my_view'
id = Column(Integer, primary_key=True)
col = Column(Integer)
因为映射器知道正在映射哪些列,并且只会在查询语句中使用这些列。
这样就不太好了:
my_view = Table('my_view', Base.metadata, autoload_with=engine)
class MyModel(Base):
__table__ = my_view
因为映射器将使用反射表中的所有列。