1

特定のスキーマを持つデータベースを持つプログラムがありますv0.1.0

次のバージョン ( v0.1.1) では、データベース スキーマに変更を加えました。

したがって、( ) に更新するときに、( ) 以降のバージョン0.1.1の元のデータに影響を与えることなく、これらの変更を有効にしたいと考えています。0.1.0

0.1.0( ) データベース データに影響を与えずに変更を加え、その後のバージョンでそれらの変更を追跡するにはどうすればよいですか?

でpythonを使用していsqlite3ます。

アップデート

ソフトウェアの複数のバージョンはサポートされていません。データベースは、使用しているバージョンによって異なります。

データベースへの同時アクセスはなく、バージョンごとに 1 つのデータベースです。

したがって、ユーザーは古いバージョンを使用できますが、新しいバージョンにアップグレードすると、.sqlite スキーマが変更されます。

4

3 に答える 3

4

user_versionPRAGMAを使用してデータベースのスキーマ バージョンを追跡し、一連のアップグレード手順を維持します。

def get_schema_version(conn):
    cursor = conn.execute('PRAGMA user_version')
    return cursor.fetchone()[0]

def set_schema_version(conn, version):
    conn.execute('PRAGMA user_version={:d}'.format(version))

def initial_schema(conn):
    # install initial schema
    # ...

def ugrade_1_2(conn):
    # modify schema, alter data, etc.

# map target schema version to upgrade step from previous version
upgrade_steps = {
    1: initial_schema,
    2: ugrade_1_2,
}

def check_upgrade(conn):
    current = get_schema_version(conn)
    target = max(upgrade_steps)
    for step in range(current + 1, target + 1):
        if step in upgrade_steps:
            upgrade_steps[step](conn)
            set_schema_version(conn, step)
于 2013-10-12T08:48:21.887 に答える
0

これにはいくつかの方法がありますが、ここでは 1 つだけ説明します。

データベース内ですでにバージョンを追跡しているようです。アプリケーションの起動時に、実行中のアプリケーションのバージョンに対してこのバージョンを確認し、スキーマの変更を実行する SQL スクリプトを実行する必要があります。

アップデート

実際の例:

import os
import sqlite3 as sqlite

def make_movie_table(cursor):
    cursor.execute('CREATE TABLE movies(id INTEGER PRIMARY KEY, title VARCHAR(20), link VARCHAR(20))')

def make_series_table(cursor):
     cursor.execute('CREATE TABLE series(title VARCHAR(30) PRIMARY KEY,series_link VARCHAR(60),number_of_episodes INTEGER,number_of_seasons INTEGER)')

def make_episode_table(cursor):
    cursor.execute('CREATE TABLE episodes(id INTEGER PRIMARY KEY,title VARCHAR(30),episode_name VARCHAR(15), episode_link VARCHAR(40), Date TIMESTAMP, FOREIGN KEY (title) REFERENCES series(title) ON DELETE CASCADE)')

def make_version_table(cursor):
    cursor.execute('CREATE TABLE schema_versions(version VARCHAR(6))')
    cursor.execute('insert into schema_versions(version) values ("0.1.0")')

def create_database(sqlite_file):
    if not os.path.exists(sqlite_file):
        connection = sqlite.connect(sqlite_file)
        cursor = connection.cursor()
        cursor.execute("PRAGMA foreign_keys = ON")
        make_movie_table(cursor)
        make_series_table(cursor)
        make_episode_table(cursor)
        make_version_table(cursor)
        connection.commit()
        connection.close()

def upgrade_database(sqlite_file):
    if os.path.exists(sqlite_file):
        connection = sqlite.connect(sqlite_file)
        cursor = connection.cursor()

        cursor.execute("select max(version) from schema_versions")
        row = cursor.fetchone()
        database_version = row[0]
        print('current version is %s' % database_version)

        if database_version == '0.1.0':
            print('upgrading version to 0.1.1')
            cursor.execute('alter table series ADD COLUMN new_column1 VARCHAR(10)')
            cursor.execute('alter table series ADD COLUMN new_column2 INTEGER')
            cursor.execute('insert into schema_versions(version) values ("0.1.1")')

        #if database_version == '0.1.1':
            #print('upgrading version to 0.1.2')
            #etc cetera

        connection.commit()
        connection.close()

#I need to add 2 columns to the series table, when the user upgrade the software.

if __name__ == '__main__':
    create_database('/tmp/db.sqlite')
    upgrade_database('/tmp/db.sqlite')

各アップグレード スクリプトはデータベースの変更を処理し、DB 内のバージョンを最新バージョンに更新します。ステートメントを使用していないことに注意してくださいelif。これは、必要に応じてデータベースを複数のバージョンにアップグレードできるようにするためです。

注意すべきいくつかの注意事項があります。

  • トランザクション内でアップグレードを実行する場合、エラーが発生した場合はロールバックして、データベースが使用できない状態にならないようにする必要があります。--指摘されたように、これは正しくありません。Martijn に感謝します
  • 可能であれば、名前の変更と列の削除を避け、必要であれば、それらを使用するビューも更新されるようにしてください。
于 2013-10-12T08:17:43.470 に答える