扑扑中的SQLite迁移

时间:2020-05-12 10:42:49

标签: database sqlite flutter migration sqflite

我正在使用flutter SQflite将数据存储在flutter中,到目前为止,我对此没有任何问题。现在,我想用它更新我的应用程序和数据库。到目前为止,我只是用新数据库替换了旧数据库。但是现在有一些表我想保留数据(用户数据)。如何更换某些桌子并保留其他桌子? (到目前为止,表结构没有改变) 编辑:我正在使用SQlite的数据库浏览器创建和填充Flutter之外的数据库(当然,应用数据中的用户除外)

     Future<void> initDatabase() async {
    var databasesPath = await getDatabasesPath();
    var path = join(databasesPath, "recipes.db");

// Check if the database exists
    var exists = await databaseExists(path);

    if (!exists) {
      // Should happen only the first time you launch your application
      print("Creating new copy of database from asset");

      // Make sure the parent directory exists
      try {
        await Directory(dirname(path)).create(recursive: true);
      } catch (_) {}

      // Copy from asset
      ByteData data = await rootBundle.load(join("assets", "recipes.db"));
      List<int> bytes =
      data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);

      // Write and flush the bytes written
      await File(path).writeAsBytes(bytes, flush: true);

    } else {
      print("Opening existing database");
    }
// open the database

    db = await openDatabase(path,version: 2, readOnly: false);
  }

2 个答案:

答案 0 :(得分:2)

迁移示例。

在下面的代码中,“ openDatabase”方法按以下顺序进行:

  • 尝试通过参数中提供的链接恢复数据库

  • 如果数据库不存在,则该方法将执行onCreate参数中提供的代码

  • 如果数据库存在,则该方法将检查数据库的版本并将其与作为参数提供的版本号进行比较。

  • 如果数据库的版本与作为参数提供的版本不匹配,则该方法将执行onUpgrade参数的代码。

基于中篇文章,但未使用“ sqlite_migration”包

例如,我正在初始化一个包含id和first_name列的users表。

// I use a map for more readability, the key represents the version of the db
  Map<int, String> migrationScripts = {
    1: '''CREATE TABLE users (
              id INTEGER PRIMARY KEY,
              first_name TEXT)
              '''
  };

  Future initDatabase() async {
    // count the number of scripts to define the version of the database
    int nbrMigrationScripts = migrationScripts.length;
    var db = await openDatabase(
      join(await getDatabasesPath(), "database.db"),
      version: nbrMigrationScripts,
      // if the database does not exist, onCreate executes all the sql requests of the "migrationScripts" map
      onCreate: (Database db, int version) async {
        for (int i = 1; i <= nbrMigrationScripts; i++) {
          await db.execute(migrationScripts[i]);
        }
      },
      /// if the database exists but the version of the database is different 
      /// from the version defined in parameter, onUpgrade will execute all sql requests greater than the old version
      onUpgrade: (db, oldVersion, newVersion) async {
        for (int i = oldVersion + 1; i <= newVersion; i++) {
          await db.execute(migrationScripts[i]);
        }
      },
    );
    return db;
  }

现在,如果要添加last_name列,我只需要在“ migrationScripts”映射中添加sql查询。

Map<int, String> migrationScripts = {
    1: '''CREATE TABLE users (
              id INTEGER PRIMARY KEY,
              first_name TEXT)
              ''',
    2: 'ALTER TABLE users ADD last_name TEXT'
  };
  • 如果用户已经具有版本1数据库, onUpgrade将运行地图的第二个脚本

  • 如果用户刚刚安装了应用程序 onCreate将执行地图的两个脚本。

答案 1 :(得分:0)

this medium中查看如何设置迁移过程,作者甚至创建了package来清理整个过程。它有点旧,但仍然可以承受。我是在建立3个月大的应用程序时使用它的。

此插件应帮助您组织将创建/更改/删除任何所需表的SQL查询组织为可在数据库初始化时运行的迁移。我建议从本文的做法,从在数据库浏览器中创建数据库转为使用SQL查询,以将所有内容都放在一个地方。