Flutter中的Sqlite迁移

23c0lvtd  于 2022-11-15  发布在  SQLite
关注(0)|答案(2)|浏览(166)

我正在使用Ffltter SQflite来存储Ffltter中的数据,到目前为止,我还没有遇到任何问题。现在我想用它更新我的应用程序和数据库。到目前为止,我只是用新的数据库替换旧的数据库。但是现在有一些表我想保存在那里的数据(用户数据)。我怎样才能更换一些table并保留另一些table呢?(表结构到目前为止还没有改变)编辑:我正在使用SQlite的DB浏览器在Ffltter外部创建和填充数据库(当然,除了应用程序数据中的用户)

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);
  }
xe55xuns

xe55xuns1#

这是一个迁移的例子。
在下面的代码中,“OpenDatabase”方法的顺序如下:

  • 尝试通过参数中提供的链接恢复数据库
  • 如果数据库不存在,该方法将执行onCreate参数中提供的代码
  • 如果数据库存在,该方法将检查数据库的版本,并将其与作为参数提供的版本号进行比较。
  • 如果数据库的版本与作为参数提供的版本不对应,则该方法将执行onUpgrade参数的代码。

基于Medium文章,但没有使用“SQLite_Migration”包
在本例中,我正在初始化一个USERS表,该表包含一个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;
  }

现在,如果我想添加一个LAST_NAME列,我只需在“MigrationScript”Map中添加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将运行Map的第二个脚本
  • 如果用户刚刚安装了应用程序,则onCreate将执行Map的两个脚本。

编辑:多表用例

Map<int, String> migrationScripts = {
    1: '''CREATE TABLE users (
              id INTEGER PRIMARY KEY,
              first_name TEXT)
              ''',
    2: 'ALTER TABLE users ADD last_name TEXT',
    3: '''CREATE TABLE posts (
              id INTEGER PRIMARY KEY,
              user_id INTEGER,
              content TEXT)
              ''',
    4: 'ALTER TABLE posts ADD title TEXT',
    5: 'ALTER TABLE users ADD age INTEGER'
  };
nbysray5

nbysray52#

查看this medium文章,它贯穿了如何设置迁移,作者甚至创建了一个package来清理整个过程。它有点旧了,但应该还能挺得住。我在设置我的应用程序时使用了它,这款应用程序已经使用了3个月。
这个插件应该可以帮助你将创建/修改/删除任何你想要的表的SQL查询组织成可以在数据库初始化时运行的迁移。我建议从在DB浏览器中创建数据库转向使用SQL查询,就像本文所做的那样,将所有东西都保存在一个地方。

相关问题