Перенос данных из одной базы данных sqlite в несколько баз данных SQLite с использованием SQLObject - PullRequest
3 голосов
/ 26 ноября 2011

До сих пор наше приложение использовало одну базу данных SQLite с SQLObject в качестве ORM.Очевидно, в какой-то момент мы знали, что должны столкнуться с проблемой параллелизма SQLite, и мы это сделали.

В итоге мы разбили текущую базу данных на несколько баз данных.Это означает, что каждая схема таблиц осталась прежней, но мы распределили разные таблицы по нескольким базам данных, сохраняя тесно связанные таблицы.

Теперь это работает очень хорошо при чистой установке новой версии нашего приложения, но при обновлении до предыдущих версийнаше приложение для этой новой версии требует специальной миграции данных, прежде чем наше приложение сможет начать работать.В этом случае миграция базы данных - это простое перемещение таблиц из этой единой базы данных в соответствующие разные базы данных.

В качестве примера рассмотрим старую структуру:

single_db.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

Когда произойдет обновление, наше приложение создаст новую структуру с тремя вышеуказанными базами данных и пустыми таблицами в них.Также там будет более старая база данных single_db.db со всеми таблицами и фактическими данными.Теперь, прежде чем наше приложение сможет начать работать, оно должно переместить таблицы или, я бы сказал, скопировать данные из таблицы из более старой базы данных в соответствующую таблицу в соответствующей новой базе данных.

Мне нужно будет написать код для этой миграции базы данных.Я знаю, что могу запросить таблицу, используя старое соединение с базой данных, и вставить возвращенные строки в соответствующую таблицу, используя более новое соединение с базой данных.Я должен упомянуть здесь одно предостережение: некоторые из этих таблиц могут содержать большое количество строк.То есть строк в 2/3 таблицах может быть до 2–2,5 млн.

Поэтому я хочу спросить, могу ли я использовать другие приемы SLQObject, поскольку я использую SQLObject поверх SQLite, а также кто-нибудь делал это раньше?

Спасибо за помощь.

1 Ответ

1 голос
/ 29 июня 2012

Я понимаю, что вы, вероятно, уже решили эту проблему, но для любого, прибегая к помощи в поиске, я должен был сделать почти то же самое, что и 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 строк, чтобы я мог показать прогресс при миграции.

...