使用SQLObject将数据从一个SQLite数据库迁移到多个SQLite数据库

3
到目前为止,我们的应用程序一直使用一个SQLite数据库,并使用SQLObject作为ORM。显然,在某个时刻,我们知道我们必须面对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 --- Database 3

 - F -- Table F

当升级发生时,我们的应用程序将使用上述3个数据库创建新结构,并在其中创建空表。同时,旧的single_db.db数据库将保留所有表和实际数据。现在,在应用程序开始工作之前,它应该移动表或者说是将旧数据库中的一个表的数据复制到相应的新数据库中的相应表中。
我需要编写这个数据库迁移的代码。我知道我可以使用旧的数据库连接查询表,并使用新的数据库连接将返回的行插入到相应的表中。这里需要提醒的是,其中一些表可能包含大量行。也就是说,2/3个表中的行数可能达到200-250万。
所以我想问一下,我是否可以使用任何其他的SLQObject技巧,因为我正在使用基于SQLite的SQLObject,还有没有人做过这件事?
感谢您的帮助。
1个回答

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行时递增了计数器,以便可以显示迁移进度。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接