FMDB:添加新列并插入数据
Posted
技术标签:
【中文标题】FMDB:添加新列并插入数据【英文标题】:FMDB: add new column and insert data 【发布时间】:2014-01-19 03:29:28 【问题描述】:在我的应用中,我使用的是FMDatabase
。我正在尝试将新的column
添加到现有的table
,然后在该列中添加insert
数据。当我通过Alter Table
添加列时,我没有收到任何错误,但是当我尝试在表中插入数据时,我收到错误,抱怨新添加的列不存在。
这是我的代码
NSString *databasePath = [myDB getPlacesDBPath];
FMDatabase *db = [FMDatabase databaseWithPath:databasePath];
if (![db open])
return ;
if (![db columnExists:@"placeName" inTableWithName:@"MYPLACES"])
[db executeQuery:@"ALTER TABLE MYPLACES ADD COLUMN placeName TEXT"];
// I tried to set the result of this query in "BOOL Success" and print the results and I got YES
//Note: I have more than 12 columns but I didn't post all of them here
NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO MYPLACES ( placeID , placeName) VALUES (\"%@\", \"%@\")", placeIDValue, placeNameValue ];
[db executeUpdate:insertSQL];
if ([db hadError])
NSLog(@"error : %@",[db lastError]);
[db close];
我收到以下错误:
error : Error Domain=FMDatabase Code=1 "table MYPLACES has no column named placeName" UserInfo=0xe340920 NSLocalizedDescription=table MYPLACES has no column named placeName
有什么问题?如何知道为什么没有添加新列?
【问题讨论】:
【参考方案1】:我在上面的简化代码示例中没有看到任何内容来解释您报告的错误。问题可能存在于其他地方(或者,可能在简化代码示例的过程中,您消除了问题的根源)。
话虽如此,我有几个反应:
你说:
我尝试在“BOOL Success”中设置此查询的结果并打印结果,我得到了 YES
我不知道这怎么可能,因为 executeQuery
返回的是 FMResultSet
而不是 BOOL
。不过,这没有实际意义,因为您的ALTER TABLE
语句应该使用executeUpdate
而不是executeQuery
执行。 (后者应该仍然有效,但前者更符合逻辑。)
我不明白您为什么删除了错误检查。这是识别问题的最佳方式。
完全不相关,但在构建 SQL 时绝对不要使用 stringWithFormat
。您对因意外输入而导致的 SQL 失败敞开心扉(例如,如果您的某个值在其中包含双引号怎么办)。更糟糕的是,您将自己暴露在 SQL 注入攻击之下。相反,在 SQL 中使用?
占位符,然后将值作为参数传递给executeUpdate
(或executeQuery
)方法。
所以,下面的代码对我来说很好用:
BOOL success;
FMDatabase *db = [FMDatabase databaseWithPath:databasePath];
if (![db open])
NSLog(@"open failed");
return;
if (![db columnExists:@"placeName" inTableWithName:@"MYPLACES"])
success = [db executeUpdate:@"ALTER TABLE MYPLACES ADD COLUMN placeName TEXT"];
NSAssert(success, @"alter table failed: %@", [db lastErrorMessage]);
NSString *insertSQL = @"INSERT INTO MYPLACES (placeID, placeName) VALUES (?, ?)";
success = [db executeUpdate:insertSQL, placeIDValue, placeNameValue];
NSAssert(success, @"insert failed: %@", [db lastErrorMessage]);
[db close];
由于我看不出是什么导致了您描述的问题,我只能建议您在调试器中单步执行此代码,并确保它遵循您认为的路径。
【讨论】:
感谢您清晰、有条理和简单的回答。我不知道究竟是什么问题,但使用 executeUpdate 而不是 executeQuery 解决了问题。【参考方案2】:Swift 3 代码:
let db = FMDatabase(path: Util.getPath(databasePath)
guard db != nil else return
db!.open()
if !(db!.columnExists("tableName", columnName: "USERID"))
let alterTable = "ALTER TABLE tableName ADD COLUMN USERID TEXT"
if db!.executeUpdate(alterTable, withArgumentsIn: nil)
printf(“new column added”)
else
printf(“issue in operation”)
db!.close()
可能会帮助某人。 继续编码..
【讨论】:
【参考方案3】:问题是 -[FMDatabase executeQuery:] 不执行提交的指令,它只准备语句。
要执行它们,您需要执行一个“步骤”。
在内部由 -[FMResultSet next] 完成的 FMDB 中 - 通过调用 sqlite3_step( )。
因为 -executeUpdate:(与 -executeQuery 不同:)为您执行此操作并最终确定语句 - 它可能更适合此目的。
所以如果你真的需要使用-executeQuery:
FMResultSet *rs = [db executeQuery:@"ALTER TABLE MYPLACES ADD COLUMN placeName TEXT"];
[rs nextWithError:&error]; // error handling is recommended here
[rs close];
但是 -executeUpdate: 更简洁
BOOL success = [db executeUpdate:@"ALTER TABLE MYPLACES ADD COLUMN placeName TEXT"];
【讨论】:
以上是关于FMDB:添加新列并插入数据的主要内容,如果未能解决你的问题,请参考以下文章
如何在具有数百条记录的现有csv中添加新列并从数组中填充它?