You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 18:36:03