qua*_*ben 6 python sql sqlite inheritance sqlalchemy
我正在构建一个如下所示的继承表架构:
class Person(Base):
__tablename__ = 'people'
id = Column(Integer, primary_key=True)
discriminator = Column('type', String(50))
updated = Column(DateTime, server_default=func.now(), onupdate=func.now())
name = Column(String(50))
__mapper_args__ = {'polymorphic_on': discriminator}
class Engineer(Person):
__mapper_args__ = {'polymorphic_identity': 'engineer'}
start_date = Column(DateTime)
class Manager(Person):
__mapper_args__ = {'polymorphic_identity': 'manager'}
start_date = Column(DateTime)
Run Code Online (Sandbox Code Playgroud)
import os
import sys
from sqlalchemy import Column, create_engine, ForeignKey, Integer, String, DateTime
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql import func
from sqlalchemy.ext.declarative import declarative_base
try:
os.remove('test.db')
except FileNotFoundError:
pass
engine = create_engine('sqlite:///test.db', echo=True)
Session = sessionmaker(engine)
Base = declarative_base()
class People(Base):
__tablename__ = 'people'
discriminator = Column('type', String(50))
__mapper_args__ = {'polymorphic_on': discriminator}
id = Column(Integer, primary_key=True)
name = Column(String(50))
updated = Column(DateTime, server_default=func.now(), onupdate=func.now())
class Engineer(People):
__tablename__ = 'engineer'
__mapper_args__ = {'polymorphic_identity': 'engineer'}
id = Column(Integer, ForeignKey('people.id'), primary_key=True)
kind = Column(String(100), nullable=True)
Base.metadata.create_all(engine)
session = Session()
e = Engineer()
e.name = 'Mike'
session.add(e)
session.flush()
session.commit()
# works when updating the object
e.name = "Doug"
session.add(e)
session.commit()
# works using the base class for the query
count = session.query(People).filter(
People.name.is_('Doug')).update({People.name: 'James'})
# fails when using the derived class
count = session.query(Engineer).filter(
Engineer.name.is_('James')).update({Engineer.name: 'Mary'})
session.commit()
print("Count: {}".format(count))
Run Code Online (Sandbox Code Playgroud)
注意:这是来自sql docs 的稍微修改的示例
如果我尝试更新name工程师的两件事情应该发生。
nameupdatedPeople 表上的列现在,我想专注于数字 1。像下面的示例(也记录在完整代码示例中)之类的事情将导致无效的 SQL
session.query(Engineer).filter(
Engineer.name.is_('James')).update({Engineer.name: 'Mary'})
Run Code Online (Sandbox Code Playgroud)
我相信上面会产生以下内容:
更新工程师 SET name=?, updated=CURRENT_TIMESTAMP FROM people WHERE people.name IS ?
再次,这是无效的。该语句试图更新不正确表中的行。 name位于基表中。
我有点不清楚继承表应该如何工作,但似乎更新应该与派生对象透明地工作。意思是,当我更新Engineer.name对EngineerSQLAlchemy 应该知道更新People表的对象的查询时。更复杂的是,如果我尝试更新两个表中存在的列会发生什么
session.query(Engineer).filter(
Engineer.name.is_('James')).update({Engineer.name: 'Mary', Engineer.start_date: '1997-01-01'})
Run Code Online (Sandbox Code Playgroud)
我怀疑 SQLAlchemy 不会发出两个更新语句。