APP任务删除异常:无法同步删除数据库关联双表数据
解决跨表同步删除问题:删除任务时同步删除关联的跟踪记录
问题分析
当前删除任务时仅删除了tasks表的记录,task_tracked表中关联该任务ID的所有跟踪数据未被同步删除,导致数据不一致。核心原因是现有deleteTask方法未处理关联表的删除逻辑,且现有的deleteTrackTask仅针对指定日期的单条跟踪记录,而非该任务的所有跟踪数据。
解决方案
提供两种可靠的实现方式,可根据项目阶段选择:
方式一:手动事务删除(适合已上线项目,无需修改表结构)
通过数据库事务保证删除操作的原子性,先删除task_tracked表中所有关联该任务ID的记录,再删除tasks表的对应记录,避免出现部分删除成功的情况。
修改DBHelper中的deleteTask方法:
Future<void> deleteTask(int taskId) async { final db = await database; // 开启事务,确保两个删除操作要么都成功,要么都回滚 await db.transaction((txn) async { // 删除该任务对应的所有跟踪记录 await txn.delete( tableTaskTrack, where: '$columnTaskId = ?', whereArgs: [taskId], ); // 删除任务本身 await txn.delete( tableTasks, where: '$columnId = ?', whereArgs: [taskId], ); }); }
Controller层的deleteTask方法无需修改,调用现有逻辑即可完成同步删除。
方式二:SQLite外键级联删除(推荐新项目使用,更简洁)
利用SQLite的外键约束特性,设置ON DELETE CASCADE,当删除tasks表的记录时,数据库会自动删除task_tracked表中关联的所有记录。
步骤1:修改表结构,添加外键约束
创建task_tracked表时,添加外键关联tasks表的ID,并设置级联删除:
// 创建task_tracked表的SQL语句 String createTaskTrackTable() => ''' CREATE TABLE $tableTaskTrack ( $columnTaskId INTEGER, $columnTrackedDate TEXT, -- 外键关联tasks表的id,删除任务时自动删除关联跟踪记录 FOREIGN KEY ($columnTaskId) REFERENCES $tableTasks($columnId) ON DELETE CASCADE ) ''';
步骤2:开启SQLite外键支持
在DBHelper的初始化方法中开启外键功能:
Future<Database> initDB() async { String path = await getDatabasesPath(); path = join(path, 'your_task_db.db'); // 替换为你的数据库名称 return await openDatabase( path, version: 1, onCreate: (db, version) async { await db.execute(createTasksTable()); // 你的tasks表创建语句 await db.execute(createTaskTrackTable()); }, // 必须开启外键支持,否则级联删除不生效 onConfigure: (db) async { await db.execute('PRAGMA foreign_keys = ON'); }, ); }
完成以上设置后,原有的deleteTask方法无需任何修改,删除任务时数据库会自动同步删除关联的跟踪记录。
注意事项
- 若使用外键级联删除,已上线项目需处理数据库迁移,避免丢失现有数据;
- 原有的
deleteTrackTask方法用于删除指定日期的单条跟踪记录,与删除整个任务的场景不冲突,可保留用于单独删除某一天的跟踪数据。
内容的提问来源于stack exchange,提问作者Megha Choudhary
相关产品推荐
相关产品推荐

