使用SQLAlchemy进行更新和表继承的问题

时间:2017-05-25 14:49:18

标签: 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)

更新(工作)代码

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))

注意:这是sql docs

中略有修改的示例

如果我尝试为工程师更新name,那么应该发生

  1. 将语句更新到列name
  2. 上的人员表
  3. 自动触发更新人员表<{li>上的updated

    目前,我想专注于数字1。下面的示例(如完整代码示例中所述)将导致无效的SQL

    session.query(Engineer).filter(
                               Engineer.name.is_('James')).update({Engineer.name: 'Mary'})
    

    我相信以上内容会产生以下结果:

      

    UPDATE工程师SET名=?,更新= CURRENT_TIMESTAMP来自人WHERE people.name IS?

    同样,这是无效的。该语句试图更新不正​​确的表中的行。 name位于基表中。

    我有点不清楚继承表应该如何工作,但似乎更新应该与派生对象透明地工作。这意味着,当我更新Engineer.name查询Engineer对象时,SQLAlchemy应该知道更新People表。为了使事情复杂化,如果我尝试更新两个表中存在的列

    会发生什么
    session.query(Engineer).filter(
                               Engineer.name.is_('James')).update({Engineer.name: 'Mary', Engineer.start_date: '1997-01-01'})
    

    我怀疑SQLAlchemy不会发出两个更新语句。

0 个答案:

没有答案