使用FMDB提示‘no such table’,已创建对应表求排查原因
我来帮你排查这个iOS SQLite开发里的常见问题,结合你的代码和描述,大概率是以下几个原因之一:
1. 你操作的数据库和App访问的不是同一个文件
你在SQLite Manager里打开的Inventorydb.sqlite,和App运行时在Documents目录调用的,很可能是两个完全独立的文件。iOS模拟器的Documents目录藏在系统深层路径里,大概是这个格式:~/Library/Developer/CoreSimulator/Devices/[设备ID]/data/Containers/Data/Application/[App唯一ID]/Documents/
你手动在电脑本地Documents文件夹创建的数据库,App根本访问不到。
解决方法:
- 找到App沙盒里的真实数据库文件:打开Xcode的
Window > Devices and Simulators,选中你的测试App,点击「Download Container」导出沙包,解压后找到Documents目录里的Inventorydb.sqlite,再用SQLite Manager打开这个文件去操作表和数据。 - 或者把你已经建好表的数据库文件添加到Xcode项目,让App启动时自动把它复制到沙盒Documents目录。
2. App启动时自动创建了空数据库
你的代码里用FMDatabase databaseWithPath:时,如果Documents目录里没有指定的数据库文件,SQLite会自动生成一个全新的空库——这个新库自然没有你之前创建的inventorydata表。
解决方法:
先把建好表的Inventorydb.sqlite拖进Xcode项目(勾选「Copy items if needed」和你的目标App),然后修改getInstance方法,先检查沙盒里是否有数据库,没有的话从项目bundle复制过去:
+(ModelManager *) getInstance { if(!instance) { instance=[[ModelManager alloc]init]; // 获取沙盒Documents里的数据库路径 NSString *docsDbPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"Inventorydb.sqlite"]; // 获取项目bundle里的数据库路径 NSString *bundleDbPath = [[NSBundle mainBundle] pathForResource:@"Inventorydb" ofType:@"sqlite"]; // 如果沙盒里没有数据库,从bundle复制 if (![[NSFileManager defaultManager] fileExistsAtPath:docsDbPath]) { NSError *copyError; BOOL copySuccess = [[NSFileManager defaultManager] copyItemAtPath:bundleDbPath toPath:docsDbPath error:©Error]; if (!copySuccess) { NSLog(@"数据库复制失败:%@", copyError.localizedDescription); } } instance.database=[FMDatabase databaseWithPath:docsDbPath]; } return instance; }
3. 表名大小写不匹配
SQLite在iOS/macOS的文件系统上是区分大小写的,如果你在SQLite Manager里创建的表是InventoryData(首字母大写),但查询语句里用的是全小写的inventorydata,就会触发找不到表的错误。
解决方法:
打开SQLite Manager确认表名的大小写,确保和查询语句里的表名完全一致。
内容的提问来源于stack exchange,提问作者Shivam Tripathi

