Flutter使用sqflite存储数据报错,请求协助排查解决
问题排查与解决
错误原因分析
1. 参数类型不支持错误
sqflite仅支持num、String、Uint8List类型的字段值,你传入的是嵌套的_InternalLinkedHashMap(每个recipeID对应一个包含名称和分类的Map),不符合sqflite的字段类型要求。
2. SQL语法错误
你将整个recipeMap传给了insert方法,这个Map的键是Firestore中的recipeID(如101、102),sqflite错误地把这些键当成了数据库表的列名。但你的表结构里根本没有这些数字列名,同时SQL中列名不能以纯数字开头,直接导致语法报错。
修复步骤
1. 修改数据传递逻辑
不要把所有Recipe打包成一个嵌套Map,而是遍历每个Recipe,生成对应表结构的扁平Map,逐个插入数据库:
修改getRecipeData方法:
Future<void> getRecipeData() async { recipes = await RecipeModel().getRecipeDataList(); count = await RecipeModel().getRecipeCount(); final dbHelper = DatabaseHelper(); // 逐个处理每个Recipe for (int i = 0; i < count; i++) { final recipe = recipes[i]; // 生成符合表结构的扁平Map final recipeData = { 'recipeId': recipe.recipeID, 'recipeName': recipe.recipeName, 'recipe_category': recipe.recipeCategory, 'synced': 0 // 默认未同步,可根据需求调整 }; // 逐个插入数据库 await dbHelper.saveRecipe(recipeData); } }
2. 增强数据库方法健壮性(可选)
你的saveRecipe方法已适配单条Recipe的插入需求,可添加空值判断避免字段缺失:
Future<int> saveRecipe(Map<String, dynamic> recipe) async { var dbClient = await db; // 可选:添加必填字段校验 assert(recipe.containsKey('recipeId'), 'recipeId 为必填字段'); assert(recipe.containsKey('recipeName'), 'recipeName 为必填字段'); assert(recipe.containsKey('recipe_category'), 'recipe_category 为必填字段'); int res = await dbClient!.insert(recipeTable, recipe); return res; }
修复效果验证
修改后两个错误都会被解决:
- 传入的是符合表结构的扁平Map,不再有嵌套Map类型,解决参数类型不兼容问题;
- insert语句会使用正确的列名(recipeId、recipeName等),不再出现数字列名,解决SQL语法错误。
内容的提问来源于stack exchange,提问作者Ahmed Raza
相关产品推荐
相关产品推荐

