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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:27:02