我有一个程序,其中包含一个具有特定架构的数据库v0.1.0
。
在我的下一个版本(v0.1.1
)中,我对数据库架构进行了更改。
因此,当我更新到(0.1.1
)时,我希望这些更改生效,而不会影响(0.1.0
)及后续版本中的原始数据。
如何在不影响(0.1.0
)数据库数据的情况下进行更改并跟踪后续版本中的更改?
我正在使用sqlite3
的python。
更新
不支持多个版本的软件。数据库取决于您正在使用的版本。
没有并发访问数据库,每个版本有1个数据库。
因此用户可以使用旧版本,但是当他们升级到新版本时,将更改.sqlite架构。
答案 0 :(得分:4)
使用user_version
PRAGMA跟踪数据库中的架构版本,并保留一系列升级步骤:
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)
答案 1 :(得分:0)
有几种方法可以做到这一点,我只提一个。
好像你已经跟踪了数据库中的版本。在应用程序启动时,您需要根据正在运行的应用程序版本检查此版本,并运行将执行架构更改的任何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')
每个升级脚本将处理making your database changes,然后将数据库内的版本更新为最新版本。请注意,我们不使用elif
语句,因此您可以根据需要在多个版本上升级数据库。
需要注意一些注意事项:
答案 2 :(得分:-2)
长期以来,您最好使用SQLAlchemy之类的ORM和Alembic等迁移工具。