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

调用rawQuery()查询Cursor出错:外部SQLite数据库表不存在异常

解决Android中读取外部数据库提示“no such table”的问题

我来帮你排查这个问题!你遇到的SQLiteException: no such table: Calls本质是因为你实际打开的数据库和你复制的不是同一个文件,而且数据库复制的逻辑根本没执行起来。下面一步步给你解决:

问题根源分析

  1. 路径不匹配:你硬编码的DB_PATH = "/data/data/com.example.databaseDemo/"并不是SQLiteOpenHelper默认的数据库存储目录(默认是/data/data/包名/databases/),导致你复制的数据库和getReadableDatabase()打开的数据库不是同一个文件。
  2. 复制逻辑未执行:你的MainActivity只初始化了DataBaseHelper,但没有调用createDataBase()和openDataBase(),assets里的数据库根本没复制到设备上。
  3. 错误的数据库实例:getDataFromDB()里调用this.getReadableDatabase()会创建一个全新的空数据库,自然找不到Calls表。

解决方案步骤

1. 修正数据库存储路径(避免硬编码)

修改DataBaseHelper的路径获取方式,用系统API获取正确的数据库目录:

public class DataBaseHelper extends SQLiteOpenHelper {
    private static String DB_NAME = "data.db";
    private static String DB_PATH; // 去掉硬编码,动态获取
    private SQLiteDatabase myDataBase;
    private final Context myContext;
    Cursor cursor;

    public DataBaseHelper(Context context) {
        super(context, DB_NAME, null, 1);
        this.myContext = context;
        // 获取应用专属的数据库目录,适配所有Android版本
        DB_PATH = context.getDatabasePath(DB_NAME).getParent() + "/";
    }

    // 删掉你重写的getReadableDatabase()方法,不需要默认的实例
    // ... 其他原有方法保持不变 ...
}

2. 确保数据库复制和打开逻辑被执行

在MainActivity的onCreate中,先完成数据库的复制和打开操作:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // ...  RecyclerView初始化代码保持不变 ...

    helper = new DataBaseHelper(this);
    try {
        // 先检查并复制数据库到正确路径
        helper.createDataBase();
        // 打开我们复制好的数据库
        helper.openDataBase();
    } catch (IOException e) {
        e.printStackTrace();
        // 这里可以加错误提示,比如Toast
    }

    albumList = helper.getDataFromDB();
    adapter = new MainAdapter(this, albumList);
    recyclerView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
}

3. 使用正确的数据库实例查询数据

修改getDataFromDB()方法,使用我们自己打开的myDataBase,而不是默认的空数据库:

public List<Album> getDataFromDB() {
    List<Album> modelList = new ArrayList<>();
    int i = 1;
    String query = "select * from Calls where call_key = " + i;
    
    // 使用我们复制并打开的myDataBase实例
    cursor = myDataBase.rawQuery(query, null);
    
    if (cursor.moveToFirst()) {
        do {
            Album model = new Album();
            model.setName(cursor.getString(2));
            model.setNumOfSongs(cursor.getString(3));
            modelList.add(model);
        } while (cursor.moveToNext());
    }
    
    // 记得关闭Cursor,避免内存泄漏
    if (cursor != null && !cursor.isClosed()) {
        cursor.close();
    }
    
    Log.d("student data", modelList.toString());
    return modelList;
}

额外注意事项

  • 确认assets目录下的data.db确实包含Calls表,且表名大小写和代码中一致(SQLite默认大小写不敏感,但最好保持一致)。
  • 对于Android 6.0及以上版本,如果你操作的是外部存储需要动态申请权限,但这里是应用内部私有目录,不需要额外权限,Manifest里的权限已经足够。
  • 测试前可以先卸载旧应用,避免残留的空数据库影响测试结果。

内容的提问来源于stack exchange,提问作者Rakshit Sorathiya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:53:07