Flutter应用版本升级时如何修改SQLite的quiz_questions表且不改动performance_records表
Flutter SQLite 测验题目表无损升级方案
核心实现依赖sqflite包的内置版本管理机制,全程不操作performance_records表即可实现需求,具体步骤如下:
前置配置
每次发布带题目更新的新版本时,将数据库版本号+1(例如上一版版本号为1,新版改为2即可),所有升级逻辑都在onUpgrade回调中实现,该回调仅在本地数据库版本低于你设置的新版本号时自动触发。
两种更新场景的实现代码
场景1:仅追加新题目(旧题目保留不修改)
适合每次更新只加新题、原有题目不需要改动的情况,用INSERT OR IGNORE避免重复插入:
import 'package:sqflite/sqflite.dart'; // 初始化数据库代码 final db = await openDatabase( 'your_local_db_path/quiz.db', version: 2, // 每次更新题目就把这个数字+1 onCreate: (db, version) async { // 首次安装建表逻辑,同时建两个表,不影响后续升级 await db.execute(''' CREATE TABLE quiz_questions ( id INTEGER PRIMARY KEY, question TEXT NOT NULL, options TEXT NOT NULL, answer TEXT NOT NULL ) '''); await db.execute(''' CREATE TABLE performance_records ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, is_correct INTEGER NOT NULL, answer_time INTEGER NOT NULL ) '''); // 首次安装导入初始题目,从assets/quiz.db读取或者批量插入都可以 }, onUpgrade: (db, oldVersion, newVersion) async { // 全程没有任何操作performance_records表的代码,用户数据完全不受影响 if (oldVersion < 2) { // 版本2追加的新题目 await db.execute(''' INSERT OR IGNORE INTO quiz_questions (id, question, options, answer) VALUES (101, ' Flutter 中StatefulWidget的生命周期首项是?', 'initState|createState|build|dispose', 'createState'), (102, 'Dart中声明空安全的可空变量用什么符号?', '*|?|!|@', '?') '''); } // 后续版本更新继续加判断即可,比如oldVersion <3的时候加版本3的新题 }, );
场景2:全量替换quiz_questions表(旧题有修改/删除,需要用全新题目表)
适合旧题目有错别字、要删除过时题目、调整题目结构的场景,直接删除旧表重建导入新数据即可:
onUpgrade: (db, oldVersion, newVersion) async { if (oldVersion < 2) { // 仅删除旧的题目表,完全不碰作答记录表 await db.execute('DROP TABLE IF EXISTS quiz_questions'); // 新建新版题目表(如果表结构有调整也在这里改) await db.execute(''' CREATE TABLE quiz_questions ( id INTEGER PRIMARY KEY, question TEXT NOT NULL, options TEXT NOT NULL, answer TEXT NOT NULL, difficulty INTEGER DEFAULT 1 -- 新版加的难度字段 ) '''); // 方式1:从你存放在assets的新版题目文件(json/csv)读取批量插入 // 方式2:用ATTACH语句直接挂载assets里的新quiz.db,跨库导入所有题目,不需要额外转存文件 await db.execute("ATTACH 'assets/quiz.db' AS new_version_db"); await db.execute("INSERT INTO quiz_questions SELECT * FROM new_version_db.quiz_questions"); await db.execute("DETACH new_version_db"); } }
注意事项
- 所有升级操作默认在事务中执行,中途出错会自动回滚,不会损坏本地数据
- 永远不要在
onCreate/onUpgrade/onDowngrade回调中写入任何操作performance_records表的代码,即可100%保证用户作答记录不会被修改 - 不要直接用assets的quiz.db覆盖本地数据库文件,会直接删掉用户本地的作答记录表,全程只操作
quiz_questions表即可
内容的提问来源于stack exchange,提问作者Tanzilo
相关产品推荐
相关产品推荐

