sqflite查询报错no such table: BOOKS,db.query无法获取数据求助
问题分析与解决
1. 核心问题:预打包数据库未正确复制到应用沙盒
你直接尝试打开documentDirectory下的asset/database/saheeh_bukhari.db,但这个路径默认不存在——Flutter不会自动将asset目录下的文件复制到应用的沙盒目录中。此时openDatabase会创建一个空的新数据库,自然不存在books表,导致报错no such table: BOOKS。
解决步骤:
- 第一步:在pubspec.yaml中声明数据库asset
确保你的pubspec.yaml里添加了数据库文件的asset配置:
flutter: assets: - asset/database/saheeh_bukhari.db
- 第二步:修改_initDatabase方法,添加数据库复制逻辑
需要先检查目标路径是否存在数据库文件,不存在则从asset复制过去:
import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/services.dart'; // 新增导入 import 'package:sqflite/sqflite.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart'; import 'models/book.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 documentDirectory = await getApplicationDocumentsDirectory(); // 直接将数据库放在文档目录下,不要嵌套asset文件夹(原路径不存在) String path = join(documentDirectory.path, 'saheeh_bukhari.db'); // 检查数据库是否已存在 bool dbExists = await File(path).exists(); if (!dbExists) { // 从asset加载数据库文件 ByteData data = await rootBundle.load('asset/database/saheeh_bukhari.db'); Uint8List bytes = data.buffer.asUint8List( data.offsetInBytes, data.lengthInBytes, ); // 写入到目标路径 await File(path).writeAsBytes(bytes); } return await openDatabase(path); } Future<List<Book>> getBooks() async { Database db = await instance.database; // 确保表名和数据库中实际表名一致(iOS下表名大小写敏感) var books = await db.query('books'); print(books); List<Book> bookList = books.isNotEmpty ? books.map((e) => Book.fromMap(e)).toList() : []; return bookList; } }
2. FutureBuilder逻辑错误
你的Home.dart中FutureBuilder的判断逻辑完全颠倒:snapshot.hasData时显示"Loading...",这会导致数据加载完成后仍显示加载状态,而实际数据无法展示。
修正后的FutureBuilder代码:
body: Center( child: FutureBuilder<List<Book>>( future: DatabaseHelper.instance.getBooks(), builder: (BuildContext context, AsyncSnapshot<List<Book>> snapshot) { // 加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: Text("Loading...")); } // 错误状态 if (snapshot.hasError) { return Center(child: Text("加载失败: ${snapshot.error}")); } // 无数据状态 if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text("No data found.")); } // 数据展示状态 return ListView( children: snapshot.data!.map((book) { return Center( child: ListTile( title: Text(book.dari), ), ); }).toList(), ); }, ), ),
3. 额外注意事项
- 确认你的预打包数据库
saheeh_bukhari.db中确实存在名为books的表(注意iOS系统下表名大小写敏感,Android不敏感),如果数据库中表名是大写BOOKS,则db.query时要对应写'BOOKS'。 - 测试前可以先卸载旧应用,避免残留的空数据库影响结果。
内容的提问来源于stack exchange,提问作者Sulaiman Fazli
相关产品推荐
相关产品推荐

