FMDB添加新列后执行插入记录操作时崩溃问题求助
解决FMDB添加新列后插入记录崩溃的问题
看起来你遇到了一个典型的FMDB表结构变更后的适配问题,我来帮你拆解可能的原因和解决办法:
首先先回顾下你的场景:你用这段代码给tble_abc添加了默认值为0的TestColumn列:
let alterTable = "ALTER TABLE tble_abc ADD COLUMN TestColumn INTEGER default 0" if FMInst.database!.executeUpdate(alterTable, withArgumentsIn: nil) { print("new column added") } FMInst.database!.close()
之后执行插入时,在executeUpdate:error:withArgumentsInArray:orVAList:方法的while (idx < ...)循环位置崩溃,大概率是以下几个原因之一:
1. 插入SQL语句与更新后的表结构不匹配(最常见)
当你新增列后,表的总列数变多了,如果你的插入语句是不带列名的全列插入(比如INSERT INTO tble_abc VALUES (?, ?, ...)),传入的参数数量必须和总列数完全一致;如果是带列名的插入,也要保证参数和指定列一一对应。
举个例子:
- ❌ 错误写法(假设原表有2列,新增后变3列,但还是传2个参数):
NSString *insertSql = @"INSERT INTO tble_abc VALUES (?, ?)"; [FMInst.database executeUpdate:insertSql withArgumentsInArray:@[@"val1", @"val2"]];
这种情况下,FMDB在解析参数时会因为预期的列数和实际参数数量不匹配,导致循环遍历参数时越界崩溃。
- ✅ 正确写法(两种可选):
方式一:利用默认值,只插入原有列(不需要传TestColumn的参数)
方式二:显式包含新列,传入对应参数(或者传默认值0)NSString *insertSql = @"INSERT INTO tble_abc (col1, col2) VALUES (?, ?)"; [FMInst.database executeUpdate:insertSql withArgumentsInArray:@[@"val1", @"val2"]];NSString *insertSql = @"INSERT INTO tble_abc (col1, col2, TestColumn) VALUES (?, ?, ?)"; [FMInst.database executeUpdate:insertSql withArgumentsInArray:@[@"val1", @"val2", @0]];
2. 插入时使用了已关闭的数据库连接
你在添加列后调用了FMInst.database!.close(),如果插入操作前没有重新打开数据库连接,使用已关闭的连接执行操作会导致各种异常,包括崩溃。
确保插入前重新打开连接:
if (![FMInst.database open]) { NSLog(@"Failed to open database"); return; } // 执行你的插入操作 // ... // 操作完成后按需关闭连接 [FMInst.database close];
3. 复用了缓存的旧SQL语句
如果你的代码中复用了FMStatement对象来执行插入,新增列后旧的Statement缓存的表结构已经失效,继续使用会导致元数据不匹配,进而崩溃。
解决办法:
- 尽量直接使用
executeUpdate:系列方法,内部会自动处理语句的编译和释放,不需要手动管理Statement; - 如果必须手动使用Statement,每次执行前重新编译:
NSString *insertSql = @"INSERT INTO tble_abc (col1, col2) VALUES (?, ?)"; FMStatement *statement = [FMInst.database prepare:insertSql error:nil]; if (statement) { [statement executeWithArguments:@[@"val1", @"val2"]]; [statement close]; }
内容的提问来源于stack exchange,提问作者Deepak Singh
相关产品推荐
相关产品推荐

