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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 12:15:05