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

Flutter Sqflite单数据库创建多表报错问题求助

问题原因

当ContactsSqfLiteHelper首次打开laneDane.db时,数据库不存在,因此执行它的onCreate方法创建了联系人表。后续AddTxnSqfLiteHelper再打开同一个数据库时,由于数据库已存在,它的onCreate不会被触发,导致交易表从未创建,最终插入操作时提示找不到表。

解决方案

方法1:统一数据库初始化,一次性创建所有表

将两张表的创建逻辑集中到同一个onCreate方法中,确保数据库首次创建时就生成所有需要的表。推荐抽离出全局的数据库管理类,避免重复初始化逻辑:

import 'package:sqflite/sqflite.dart' as sql;
import 'package:path/path.dart' as path;

class GlobalDBHelper {
  static Database? _database;
  static const _dbName = 'laneDane.db';
  static const _dbVersion = 1;

  static Future<Database> get database async {
    if (_database != null) return _database!;

    final dir = await sql.getDatabasesPath();
    final dbPath = path.join(dir, _dbName);
    _database = await sql.openDatabase(
      dbPath,
      version: _dbVersion,
      onCreate: _createAllTables,
    );
    return _database!;
  }

  static Future<void> _createAllTables(Database db, int version) async {
    // 创建联系人表
    await db.execute(
        'CREATE TABLE contacts (id integer primary key autoincrement, user_id integer not null, name TEXT NOT NULL, profile_pic TEXT NULL, phone_id TEXT NOT NULL)');
    // 创建交易表
    await db.execute(
        'CREATE TABLE transactions (id integer primary key autoincrement, user_id integer not null, category_id integer NULL, user_contact_id TEXT NOT NULL, type TEXT NOT NULL, amount DOUBLE NOT NULL)');
  }
}

之后修改两个业务Helper的插入方法,使用全局类获取数据库实例:

ContactsSqfLiteHelper的插入方法:

static Future<int> insert(Map<String, dynamic> data) async {
  final db = await GlobalDBHelper.database;
  return await db.insert('contacts', data);
}

AddTxnSqfLiteHelper的插入方法:

static Future<int> insert(Map<String, dynamic> data) async {
  final db = await GlobalDBHelper.database;
  return await db.insert('transactions', data);
}

方法2:通过onUpgrade补建缺失表(适用于已有旧数据库的场景)

如果设备上已经存在仅含联系人表的数据库,不想删除旧数据,可以通过升级数据库版本,在onUpgrade中补建交易表:

  1. 将数据库版本号从原数值(比如1)提升至更高版本(比如2)
  2. 添加onUpgrade回调创建交易表:
static Future<Database> get database async {
  if (_database != null) return _database!;

  final dir = await sql.getDatabasesPath();
  final dbPath = path.join(dir, _dbName);
  _database = await sql.openDatabase(
    dbPath,
    version: 2, // 升级版本号
    onCreate: _onCreate,
    onUpgrade: _upgradeDatabase,
  );
  return _database!;
}

static Future<void> _upgradeDatabase(Database db, int oldVersion, int newVersion) async {
  if (oldVersion < 2) {
    // 补建交易表
    await db.execute(
        'CREATE TABLE transactions (id integer primary key autoincrement, user_id integer not null, category_id integer NULL, user_contact_id TEXT NOT NULL, type TEXT NOT NULL, amount DOUBLE NOT NULL)');
  }
}
注意事项
  • 测试前可卸载App清除旧数据库,或调用sql.deleteDatabase(dbPath)手动删除,确保新初始化逻辑生效
  • 所有操作同一数据库的Helper类,必须使用相同的数据库版本号,否则会触发版本冲突错误

内容的提问来源于stack exchange,提问作者Abdul raheem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 08:27:36