颤振中的Sqlite迁移

ouz*_*ari 8 database migration sqlite flutter sqflite

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

     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);
  }
Run Code Online (Sandbox Code Playgroud)

chr*_*ico 16

迁移的一个例子。

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

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

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

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

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

基于中等文章,但不使用“sqlite_migration”包

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

// 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;
  }
Run Code Online (Sandbox Code Playgroud)

现在,如果我想添加一个 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'
  };
Run Code Online (Sandbox Code Playgroud)
  • 如果用户已经拥有版本 1 的数据库,则 onUpgrade 将运行地图的第二个脚本

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


Gil*_*ton 1

查看这篇媒体文章,它介绍了如何设置迁移,作者甚至创建了一个来清理整个过程。它有点旧,但应该仍然保持得很好。我在设置我的应用程序时使用了它,该应用程序已经使用了 3 个月。

这个插件应该可以帮助您将创建/更改/删除任何您可能想要的表的 SQL 查询组织到可以在数据库初始化时运行的迁移中。我建议从在数据库浏览器中创建数据库转向使用 SQL 查询(如本文所述),以将所有内容保留在一个位置。