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

React Native(Expo)集成SQLite报错:表不存在(实际已创建)

Expo React Native SQLite 表不存在问题排查

问题概述

开发基于Expo的React Native应用时,集成SQLite数据库遇到以下问题:

  • 已在assets/DB目录创建数据库,其中watchme表包含1条数据,IDE中可正常查询
  • 应用启动时提示“no such table”错误
  • 该功能之前正常运行,未修改代码的情况下突然失效

相关代码

App.tsx

const configDatabase = async () => {
    const dbName = 'watchmeDB.db';
    const dbAsset = require('./assets/DB/watchmeDB.db');
    const dbUri = Asset.fromModule(dbAsset).uri;
    const dbFilePath = `${FileSystem.documentDirectory}SQLite/${dbName}`;

    try {
        FileSystem.getInfoAsync(`${FileSystem.documentDirectory}SQLite/watchmeDB.db`)
            .then(result => {
                if (result.exists) {
                    const db = SQLite.openDatabaseAsync('watchmeDB.db');
                } else {
                    FileSystem.downloadAsync(
                        Asset.fromModule(require('./assets/DB/watchmeDB.db')).uri,
                        `${FileSystem.documentDirectory}SQLite/watchmeDB.db`
                    ).then(() => {
                        const db = SQLite.openDatabaseAsync('watchmeDB.db');
                    });
                }
            });
    } catch (err) {
        console.error(err);
    }
};

...

useEffect(() => {
        configDatabase()
        .then(() => {
            setDbLoaded(true);
        })
        .catch((error) => console.error(error));
    }
,[])

...

return <SafeAreaProvider
        initialMetrics={initialWindowMetrics}
        onLayout={onLayoutRootView}
    >
        <StatusBar style="dark"/>
        <Suspense fallback={fallback}>
            <SQLite.SQLiteProvider assetSource={{ assetId: require('./assets/DB/watchmeDB.db') }}  databaseName="watchmeDB.db" useSuspense>
                <NavigationContainer theme={globalTheme}>
                    ...
                </NavigationContainer>
            </SQLite.SQLiteProvider>
        </Suspense>
    </SafeAreaProvider>

HomeScreen.tsx

const db = useSQLiteContext();

useEffect(() => {
    getData();
    // db.withTransactionAsync(async () => {
    //     await getData();
    // })
}, [db]);

async function getData() {
    const result = await db.getAllAsync<Item>(`select * from watchme`);
    console.log(result);
    // setItems(result);
}

问题原因与修复

核心问题1:异步流程未正确等待

configDatabase是async函数,但内部使用.then()链式调用却未返回Promise,导致useEffect中标记数据库加载完成的逻辑会在数据库实际准备好前执行,此时SQLiteProvider还未完成初始化,就触发了HomeScreen的查询。

修复:改用await处理异步操作,确保所有步骤完成后再标记加载完成:

const configDatabase = async () => {
    const dbName = 'watchmeDB.db';
    const dbFilePath = `${FileSystem.documentDirectory}SQLite/${dbName}`;

    try {
        const result = await FileSystem.getInfoAsync(dbFilePath);
        if (!result.exists) {
            const dbAsset = Asset.fromModule(require('./assets/DB/watchmeDB.db'));
            await dbAsset.downloadAsync();
            await FileSystem.copyAsync({
                from: dbAsset.localUri!,
                to: dbFilePath
            });
        }
    } catch (err) {
        console.error(err);
    }
};

核心问题2:手动初始化与SQLiteProvider冲突

你同时使用了手动的数据库复制逻辑和SQLiteProvider(它会自动处理数据库的复制与初始化),这会导致数据库文件加载顺序混乱,甚至被覆盖。

修复:移除手动的configDatabase逻辑,完全依赖SQLiteProvider的自动能力:

  1. 删除configDatabase函数和对应的useEffect
  2. 确保SQLiteProvider配置正确即可,它会自动检查目标路径是否存在数据库,不存在则从assets复制

额外排查点:清理旧缓存

如果之前的错误导致数据库文件损坏,可尝试:

  • 卸载应用后重新安装
  • 开发模式下执行await FileSystem.deleteAsync(${FileSystem.documentDirectory}SQLite/watchmeDB.db)清理旧文件

关于数据库读写配置

不需要额外配置,通过useSQLiteContext()获取的db实例支持所有标准SQLite操作,示例如下:

  • 插入:await db.runAsync('INSERT INTO watchme (column_name) VALUES (?)', [value])
  • 更新:await db.runAsync('UPDATE watchme SET column_name = ? WHERE id = ?', [new_value, target_id])
  • 删除:await db.runAsync('DELETE FROM watchme WHERE id = ?', [target_id])
    查询使用getAllAsync、getFirstAsync等方法即可,和你当前的查询写法一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:35:02