首页 > 解决方案 > 在另一个数据库中重新创建对象的可用 SQLAlchemy 方法有哪些?

问题描述

我正在使用 SQLAlchemy 将数据从一个数据库迁移到另一个数据库(SQLite 到 MySQL)。将所有与 DDL 相关的东西抛在脑后(因为它是一个不同的主题),我试图从一个 Engine->Connection->Session->Query 获取结果并将它们添加到另一个 DB Engine->Connection->Session 中。

假设这是我的入门代码:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

source_engine = create_engine(args.source_db_dsn)
source_session_maker = sessionmaker(autocommit=False,
                                    autoflush=False,
                                    bind=source_engine.connect())

dest_engine = create_engine(args.dest_db_dsn)
dest_session_maker = sessionmaker(autocommit=True,
                                  autoflush=True,
                                  bind=dest_engine.connect())

Base = declarative_base()
class Customer(Base):
    __tablename__ = "customer"
    id = Column(Integer, primary_key=True)
    name = Column(String(255))
    description = Column(String(255))

with source_session_maker() as source_session:

    query = source_session.query(Customer)

    with dest_session_maker.begin() as dest_session:
        dest_session.query(Customer).delete()

所以现在我们有一个准备好接受新行的干净表。

以下是我尝试过的几乎所有案例:

  1. 当对象附加到第一个会话时,这将引发异常:
dest_session.add_all(query.all())
  1. 这运行速度非常慢,因为 Load=True 会要求每个不同的记录
dest_session.merge_results(query, Load=True)
  1. 这不会添加任何东西,因为所有对象在从一个会话移动到另一个会话后仍然“持久”
dest_session.merge_results(query, Load=False)
  1. 这可以快速运行,但使用带下划线的属性对我来说看起来不合法(真的可以吗?)。除此之外,我们还有一个不必要的 Object->dict->Object 转换
dest_session.bulk_insert_mappings(Customer,
                                          (o.__dict__ for o in query.all()))

我还尝试调用 .clean()、.refresh_all()、.populate_existing(),但唯一要清除“持久”标志的是使用 Load=True 调用 .merge()。

我想能够清除合并对象上的持久状态将是最优雅的方式,但我还没有找到任何方法来操纵 SQLAlchemy 文档中的状态(因为它可能不是最好的主意,并且框架试图让你从这些事情中解脱出来。)

你们认为将一堆对象从一个数据库查询添加到另一个数据库会话的最佳选择是什么?

标签: pythonsqlalchemy

解决方案


推荐阅读