使用SQLAlchemy将行从一个表批量移动到另一个表

Jos*_*hua 5 python postgresql sqlalchemy flask

我有两个相同的表post和old_post。我有一个查询,检查旧帖子。我想将查询返回的行移到表中,old_post并从table中删除行post。

我可以通过遍历初始查询返回的结果来解决此问题,并以这种方式更新我的结果,但是我担心这效率很低,当我有1000多个行时,这会开始给我带来麻烦。如何有效地将行从一个表“批量移动”到另一个表?

r-m*_*m-n 6

您可以在 PostgreSQL 中使用通用表表达式

WITH moved_posts AS (
    DELETE FROM post
    WHERE expiry > time_stamp
    RETURNING *
)
INSERT INTO old_post
SELECT * from moved_posts
Run Code Online (Sandbox Code Playgroud)

SQLAlchemy 1.1 中将添加对 DELETE 的 CTE 支持。在当前版本中,您可以执行原始 SQL

from sqlalchemy import text

sql = text('''
WITH moved_posts AS (
    DELETE FROM post
    WHERE expiry > ?
    RETURNING *
)
INSERT INTO old_post
SELECT * from moved_posts
''')
db.session.execute(sql, [time_stamp])
db.session.commit()
Run Code Online (Sandbox Code Playgroud)

在 SQLAlchemy 1.1 中它看起来像这样

posts = Post.__table__
old_posts = OldPost.__table__
moved_posts = (
    posts.delete()
    .where(posts.c.expiry > ts)
    .returning(*(posts.c._all_columns))
    .cte('moved_posts'))
insert = (
    old_posts.insert()
    .from_select(
        [c.name for c in moved_posts.columns],
        moved_posts.select()
    ))
db.session.execute(insert)
db.session.commit()
Run Code Online (Sandbox Code Playgroud)


dav*_*ism 5

查询旧的Posts。批量插入OldPosts旧Posts'数据。批量删除旧的Posts。

keys = db.inspect(Post).columns.keys()
get_columns = lambda post: {key: getattr(post, key) for key in keys}

posts = Post.query.filter(Post.expiry > ts)
db.session.bulk_insert_mappings(OldPost, (get_columns(post) for post in posts))
posts.delete()
db.session.commit()
Run Code Online (Sandbox Code Playgroud)

该get_columns函数采用一个Post实例,并根据列键和值创建一个字典。阅读有关使用批量insert和delete操作的文档和警告。