【问题标题】:Bulk move rows from one table to another with SQLAlchemy使用 SQLAlchemy 将行从一个表批量移动到另一个表
【发布时间】:2016-07-13 11:45:06
【问题描述】:
我有两个相同的表post 和old_post。我有一个检查旧帖子的查询。我想将查询返回的行移到表old_post 中,并从表post 中删除行。
我可以通过迭代初始查询返回的结果并以这种方式更新我的结果来解决这个问题,但是我担心这非常低效并且当我有 1,000 多行时会开始给我带来问题。如何有效地将行从一个表“批量移动”到另一个表?
【问题讨论】:
标签:
python
postgresql
flask
sqlalchemy
【解决方案1】:
您可以在 PostgreSQL 中使用Common Table Expressions
WITH moved_posts AS (
DELETE FROM post
WHERE expiry > time_stamp
RETURNING *
)
INSERT INTO old_post
SELECT * from moved_posts
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()
在 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()
【解决方案2】:
查询旧的Posts。使用旧的 Posts' 数据批量插入 OldPosts。批量删除旧的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()
get_columns 函数采用Post 实例并根据列键和值创建字典。阅读有关使用批量 insert 和 delete 操作的文档和警告。