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的自动能力:
- 删除
configDatabase函数和对应的useEffect - 确保
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
相关产品推荐
相关产品推荐

