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

Flutter 使用 sqflite 如何防止删除存在关联数据的分组表记录

实现方案

方案1:应用层逻辑校验(无需修改表结构,快速实现)

你当前的deleteGroups方法逻辑写反了,现在是查询到关联item时反而执行删除,无关联时无返回值,修正如下:

Future<int> deleteGroups(int id) async {
  var dbClient = await db;
  // 查询是否有关联的item记录,group是SQL关键字需加反引号
  List<Map> items = await dbClient.query("item", where: '`group` = ?', whereArgs: [id]);
  if (items.isNotEmpty) {
    // 存在关联数据,返回自定义错误码,-1代表禁止删除
    return -1;
  } else {
    // 无关联数据,执行删除
    return await dbClient.delete("group", where: 'id = ?', whereArgs: [id]);
  }
}

你在UI层调用删除分组接口时,判断返回值即可:

  • 返回-1:弹出提示「当前分组已被商品关联,无法删除」
  • 返回1:删除成功
  • 返回0:无对应分组记录

方案2:数据库外键约束(更严谨,从底层阻止非法删除)

SQLite支持外键约束,开启后可以从数据库层面保证数据一致性,不需要每次业务层重复写校验逻辑,修改步骤如下:

  1. 开启数据库外键支持,修改initDb方法,增加onConfigure回调,同时升级数据库版本号:
initDb() async {
  io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
  String path = join(documentsDirectory.path, DB_NAME);
  var db = await openDatabase(
    path,
    version: 2, // 表结构修改,版本号+1
    onCreate: _onCreate,
    onUpgrade: _onUpgrade,
    // 开启外键支持
    onConfigure: (Database db) async {
      await db.execute('PRAGMA foreign_keys = ON');
    },
  );
  return db;
}
  1. 修改建表逻辑,修正字段类型不匹配问题,增加外键约束:
    你当前item表的group字段类型是TEXT,和group表的INTEGER类型id不匹配,需要同步修正,同时增加外键约束限制删除:
_onCreate(Database db, int version) async {
  await db.execute("""
    CREATE TABLE 'group' (
      'id' INTEGER PRIMARY KEY, 
      'code' TEXT, 
      'description' TEXT
    )
  """);
  await db.execute("""
    CREATE TABLE 'category' (
      'id' INTEGER PRIMARY KEY, 
      'code' TEXT, 
      'description' TEXT
    )
  """);
  await db.execute("""
    CREATE TABLE 'item' (
      'id' INTEGER PRIMARY KEY, 
      'code' TEXT, 
      'description' TEXT,
      'cost' REAL,
      'price' REAL,
      'category' INTEGER,
      'group' INTEGER,
      -- 外键约束,关联group表id,删除时限制
      FOREIGN KEY ('group') REFERENCES 'group'(id) ON DELETE RESTRICT,
      FOREIGN KEY ('category') REFERENCES 'category'(id) ON DELETE RESTRICT
    )
  """);
}
  1. 增加onUpgrade逻辑处理版本升级(开发阶段可以直接卸载App重装跳过这步,线上环境需要写迁移逻辑):
_onUpgrade(Database db, int oldVersion, int newVersion) async {
  if (oldVersion < 2) {
    // 示例:删除旧表重新创建,生产环境建议做数据迁移
    await db.execute("DROP TABLE IF EXISTS item");
    await db.execute("DROP TABLE IF EXISTS 'group'");
    await db.execute("DROP TABLE IF EXISTS category");
    await _onCreate(db, newVersion);
  }
}
  1. 捕获外键约束异常处理删除逻辑:
Future<int> deleteGroups(int id) async {
  var dbClient = await db;
  try {
    return await dbClient.delete("group", where: 'id = ?', whereArgs: [id]);
  } catch (e) {
    // 外键约束触发,存在关联数据无法删除,返回错误码
    return -1;
  }
}

内容的提问来源于stack exchange,提问作者Jian Yuan Ng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 00:57:02