【问题标题】:sqlalchemy import export failing on IntegrityErrorsqlalchemy 导入导出在 IntegrityError 上失败
【发布时间】:2013-06-27 09:44:53
【问题描述】:

我正在使用序列化程序转储和加载编写一个 sqlalchemy 导入/导出脚本。 出口工作,但我有进口问题,主要是由于外键问题。 我正在使用 sorted_tables 来获取基于依赖关系排序的表列表,这确保我不会有跨表外键问题,但是否有类似处理内部外键(指向自身的表)的东西?

我基本上在考虑两种可能的解决方案:

  1. 找到一种基于依赖关系对行进行排序的方法
  2. 禁用所有约束 -> 插入数据 -> 启用所有约束 再次

但我不确定如何正确执行此操作...

表格示例:

class Employee(Base):
    __tablename__ = "t_employee"

    id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), primary_key=True, nullable=False)
    first_name = sa.Column(sa.String(30))
    last_name = sa.Column(sa.String(30))
    manager_id  = sa.Column(Identifier, sa.ForeignKey("t_employee.id", ondelete='SET NULL'))

这是我的脚本:

def export_db(tar_file):
    print "Exporting Database. This may take some time. Please wait ..."

    Base.metadata.create_all(engine)
    tables = Base.metadata.tables

    with tarfile.open(tar_file, "w:bz2") as tar:
        for tbl in tables:
            print "Exporting table %s ..." % tbl
            table_dump = dumps(engine.execute(tables[tbl].select()).fetchall())

            ti = tarfile.TarInfo(tbl)
            ti.size = len(table_dump)
            tar.addfile(ti, StringIO(table_dump))

    print "Database exported! Exiting!"

    exit(0)

def import_db(tar_file):
    print "Importing to Database. This may take some time. Please wait ..."

    print "Dropping all tables ..."
    Base.metadata.drop_all(engine)

    print "Creating all tables ..."
    Base.metadata.create_all(engine)
    tables = Base.metadata.sorted_tables

    with tarfile.open(tar_file, "r:bz2") as tar:
        for tbl in tables:
            try:
                entry = tar.getmember(tbl.name)
                print "Importing table %s ..." % entry.name
                fileobj = tar.extractfile(entry)
                table_dump = loads(fileobj.read(), Base.metadata, db)
                for data in table_dump:
                    db.execute(tbl.insert(), strip_unicode(dict(**data)))
            except:
                traceback.print_exc(file=sys.stdout)
                exit(0)
        db.commit()

    print "Database imported! Exiting!"

    exit(0)

【问题讨论】:

    标签: import sqlalchemy


    【解决方案1】:

    对于大量转储,标准技术是禁用约束,执行导入,然后重新启用它们。您还将获得更快的插入性能。

    【讨论】:

    • 这很好,但我如何在 sqlalchemy 中做到这一点?有什么简单的方法吗?
    • 您需要发出适当的 SQL 指令来实现这一点。例如,this answer 说明在 Postgresql 上您可以使用命令“SET CONSTRAINTS ALL DEFERRED”。另一种方法是使用 SQLAlchemy 来反映所有约束,然后显式删除它们,然后重新创建它们 - 您可以从配方 here 中提出一些想法,这可能会有所帮助。
    • 谢谢,它看起来确实是一个可能的方向,尽管我很奇怪这是最简单的方法。如果我找不到更简单的方法,我会采用这种方法。
    • 谢谢@zzzeek,我最终使用了你建议的技术
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多