【问题标题】:Migrating data from one sqlite database to multiple SQLite databases using SQLObject使用 SQLObject 将数据从一个 sqlite 数据库迁移到多个 SQLite 数据库
【发布时间】:2011-11-26 18:15:19
【问题描述】:

到目前为止,我们的应用程序一直在使用一个以 SQLObject 作为 ORM 的 SQLite 数据库。显然,在某些时候我们知道我们必须面对 SQLite 并发问题,所以我们做到了。

我们最终将当前数据库拆分为多个数据库。这意味着每个表架构保持不变,但我们将不同的表分布到多个数据库中,将紧密耦合的表保持在一起。

现在这在全新安装我们的应用程序的新版本时效果很好,但是升级到我们应用程序的以前版本到这个新版本需要特殊的数据迁移,然后我们的应用程序才能开始工作。在这种情况下,数据库迁移很简单,将单个数据库中的表移动到适当的不同数据库中。

举例来说,考虑这是较旧的结构:

single_db.db --- 单个数据库

 * A -- Table A
 * B -- Table B
 * C -- Table C
 * D -- Table D
 * E -- Table E
 * F -- Table F

新结构:

db1.db --- 数据库 1

 - A -- Table A
 - B -- Table B
 - C -- Table C
 - D -- Table D

db2.db --- 数据库 2

 - E -- Table E

db3.db --- 数据库 3

 - F -- Table F

当升级发生时,我们的应用程序将使用上述 3 个数据库和其中的空表创建新结构。带有所有表和实际数据的旧数据库 single_db.db 也将在那里。现在,在我们的应用程序开始工作之前,它应该移动表,或者我应该说将旧数据库中的表中的数据复制到相应新数据库中的相应表中。

我需要为此数据库迁移编写代码。我知道我可以使用较旧的数据库连接查询表,并使用较新的数据库连接将返回的行插入到相应的表中。我应该在这里提到的一个警告是,其中一些表可以包含大量行。也就是说,2/3 表中的行数可以达到 2 - 250 万。

所以想问一下我是否可以使用任何其他 SLQObject 技巧,因为我在 SQLite 之上使用 SQLObject 并且之前也有人这样做过?

感谢您的帮助。

【问题讨论】:

    标签: python sqlite migration sqlobject


    【解决方案1】:

    我意识到你现在可能已经解决了这个问题,但是对于任何使用谷歌搜索的人来说,我必须做与 OP 几乎完全相同的操作,这是我使用的代码的核心部分(它是根据我找到的东西修改的,但我可以'找不到它来感谢原作者,道歉!)

    def _iterdump(connection, table_name):
        """
        Returns an iterator to dump a database table in SQL text format.
        """
    
        cu = connection.cursor()
    
        yield('BEGIN TRANSACTION;')
    
        # sqlite_master table contains the SQL CREATE statements for the database.
        q = """
           SELECT name, type, sql
            FROM sqlite_master
                WHERE sql NOT NULL AND
                type == 'table' AND
                name == :table_name
            """
        schema_res = cu.execute(q, {'table_name': table_name})
        for table_name, type, sql in schema_res.fetchall():
            if table_name == 'sqlite_sequence':
                yield('DELETE FROM sqlite_sequence;')
            elif table_name == 'sqlite_stat1':
                yield('ANALYZE sqlite_master;')
            elif table_name.startswith('sqlite_'):
                continue
            else:
                yield('%s;' % sql)
    
            # Build the insert statement for each row of the current table
            res = cu.execute("PRAGMA table_info('%s')" % table_name)
            column_names = [str(table_info[1]) for table_info in res.fetchall()]
            q = "SELECT 'INSERT INTO \"%(tbl_name)s\" VALUES("
            q += ",".join(["'||quote(" + col + ")||'" for col in column_names])
            q += ")' FROM '%(tbl_name)s'"
            query_res = cu.execute(q % {'tbl_name': table_name})
            for row in query_res:
                yield("%s;" % row[0])
    

    如果您传递原始数据库的 sqlite 连接和原始数据库中表的名称,此生成器将返回您可以传递的命令,以便在新数据库的 sqlite 对象上执行。

    当我这样做时,我还首先对所有表进行了行计数,并在执行INSERT 行时增加了一个计数器,以便显示迁移进度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-12
      • 2016-09-04
      • 1970-01-01
      • 2021-09-21
      • 2020-02-28
      • 2023-01-11
      • 1970-01-01
      • 2013-10-09
      相关资源
      最近更新 更多