【问题标题】:Sqlite migration in flutterFlutter中的Sqlite迁移
【发布时间】:2020-05-12 10:42:49
【问题描述】:

我正在使用flutter SQflite将数据存储在flutter中,到目前为止我没有任何问题。现在我想用它更新我的应用程序和数据库。到目前为止,我只是用新数据库替换旧数据库。但现在有一些表我想保留数据(用户数据)。我怎样才能更换一些桌子并保留其他桌子? (到目前为止,表结构没有变化) 编辑:我正在使用用于 SQlite 的 DB 浏览器在 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);
  }

【问题讨论】:

    标签: database sqlite flutter migration sqflite


    【解决方案1】:

    迁移示例。

    在下面的代码中,“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 会执行地图的两个脚本。

    编辑: 多表用例

    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'
      };
    

    【讨论】:

    • 如果我有多个表要修改,那么它将如何工作?
    • @nirvar 我用一个例子修改了我的帖子,或者我创建了一个新表并修改了两个表。
    【解决方案2】:

    查看this medium 的帖子,它介绍了如何设置迁移,作者甚至创建了一个package 来清理整个过程。它有点旧,但应该还能很好地支撑。我在设置我的应用程序时使用了它,它已经 3 个月大了。

    这个插件应该可以帮助您将创建/更改/删除您可能想要的任何表的 SQL 查询组织到可以在数据库初始化时运行的迁移中。我建议从在您的数据库浏览器中创建数据库转变为使用 SQL 查询,就像这篇文章一样,将所有内容保存在一个地方。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-08
      • 2016-09-06
      • 2014-03-24
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 2011-11-05
      • 1970-01-01
      相关资源
      最近更新 更多