Flutter使用SQFlite查询links表时报no such table错误如何解决
核心错误定位
开头几条sun/misc/Unsafe相关的警告属于Android系统层级的灰名单API访问提示,和本次报错无关,不需要处理。核心错误是no such table: links,根因是数据库初始化逻辑存在两处严重问题:
- 路径不一致:
_initDatabase方法中给openDatabase传入的数据库路径是getApplicationDocumentsDirectory()目录下的DSA_Database.db,但_onCreate回调中复制assets预置数据库时,写入的是getDatabasesPath()目录下的同名文件,两者是完全不同的路径,最终你打开的是getApplicationDocumentsDirectory()下的全新空数据库,自然不存在links表。 - 逻辑时序错误:
onCreate是SQFlite完成空数据库创建后触发的回调,你在回调内再次删除数据库的逻辑完全多余,也不符合预置数据库的加载逻辑。
修复代码
直接把预置数据库复制逻辑从onCreate移到初始化阶段,先判断目标路径是否存在数据库文件,不存在则复制assets的预置库,再打开数据库:
import 'dart:io'; import 'package:flutter/services.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sqflite/sqflite.dart'; import 'model.dart'; class DatabaseHelper { DatabaseHelper._privateConstructor(); static final DatabaseHelper instance = DatabaseHelper._privateConstructor(); static Database? _database; Future<Database> get database async => _database ??= await _initDatabase(); Future<Database> _initDatabase() async { Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, 'DSA_Database.db'); // 先判断目标路径是否已存在数据库 bool dbExists = await File(path).exists(); if (!dbExists) { // 不存在则从assets复制预置库 ByteData data = await rootBundle.load(join('assets', 'DSA_Database.db')); List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); await File(path).writeAsBytes(bytes, flush: true); } // 打开已经复制好的数据库 return await openDatabase(path, version: 1); } Future<List<Titles>> getTitles() async { Database db = await instance.database; var titles = await db.rawQuery('SELECT * FROM links'); List<Titles> titlesList = titles.isNotEmpty ? titles.map((e) => Titles.fromMap(e)).toList() : []; return titlesList; } }
如果需要把数据库存在getDatabasesPath()目录下,只需要把_initDatabase里的路径生成逻辑统一替换为getDatabasesPath()即可,只要保证复制路径和打开路径完全一致就可以。
后续验证步骤
- 先卸载测试设备上的原有应用,删除本地已经生成的空数据库缓存
- 确认
pubspec.yaml中已经正确声明了assets下的数据库文件,配置示例:
flutter: assets: - assets/DSA_Database.db
- 用SQLite可视化工具打开你assets目录下的
DSA_Database.db,确认links表确实存在,字段定义和你的Titles.fromMap逻辑匹配。
内容的提问来源于stack exchange,提问作者EisGlockner
相关产品推荐
相关产品推荐

