PostgreSQL表继承和移动行与SQLAlchemy

时间:2016-02-05 17:57:59

标签: python postgresql inheritance orm sqlalchemy

在我的应用程序(python,postgres,sqlalchemy)中,我有一个大表tasks。该应用程序主要使用tasks中最近的1k行,经常选择和更新行。由于tasks的大小,这种频繁的操作太慢,所以我决定将此表拆分为两个tasks tasks_all,其中表taskstasks_all继承(postgresql功能)。

因此,应用程序可以非常快速地使用小表,当它对旧数据执行某些操作时,它可以与大表一起使用,包括来自self和来自其后续行的所有行。

以下是我的表的简化类:

class TaskBase:
    def __init__(self, id, parent_id, data):
        self.id = id
        self.parent_id = parent_id
        self.data = data

    def __repr__(self):
        return '<Task: {} {}>'.format(self.id, self.data)


class Task(TaskBase, Base):
    __tablename__ = 'tasks'

    id = Column(INT, primary_key=True)
    parent_id = Column(INT, ForeignKey('tasks.id'))
    data = Column(TEXT)

    children = relationship("Task", backref=backref('parent', remote_side=[id]))


class TaskAll(TaskBase, Base):
    __tablename__ = 'tasks_all'

    id = Column(INT, primary_key=True)
    parent_id = Column(INT, ForeignKey('tasks_all.id'))
    data = Column(TEXT)

    children = relationship("TaskAll", backref=backref('parent', remote_side=[id]))

为了使tasks表格保持较小,我需要时间将行从tasks移至tasks_all。有时我需要将它们移回去。以下代码是我尝试实现移动的方式。

def move_group(ids):
    query = session.query(TaskAll).filter(TaskAll.id in ids)
    db_session.s.execute(insert(Task).from_select((
        TaskAll.id,
        TaskAll.parent_id,
        TaskAll.data,
    ), query))
    print("insert from select is successful")
    query.delete()
    print("delete is successful")

但这不起作用,因为表tasks_alltasks的父级,从tasks_all删除也会从tasks删除。产生的SQL查询是:

DELETE FROM tasks_all WHERE tasks_all.id IN (...);

但是为了执行我需要的操作,查询应该是

DELETE FROM ONLY tasks_all WHERE tasks_all.id IN (...);

据我所知,SQLAlchemy对ONLY一无所知。我是否必须使用sqla跳过ORM部分的原始SQL查询,或者可能有更好的解决方案将行从一个表移动到另一个表?

1 个答案:

答案 0 :(得分:1)

我发现SQLAlchemy具有提示机制,在对继承的表进行操作时会有所帮助。

def move_group(ids):
    query = session.query(TaskAll).filter(TaskAll.id in ids)
    db_session.s.execute(insert(Task).from_select((
        TaskAll.id,
        TaskAll.parent_id,
        TaskAll.data,
    ), query))
    print("insert from select is successful")
    query.delete().with_hint('ONLY', dialect_name='postgresql')
    print("delete is successful")

我知道这个问题是在几年前提出的,但我希望它仍然可以对某人有所帮助。