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:添加新列并插入数据的主要内容,如果未能解决你的问题,请参考以下文章

在jquery数据表中动态添加列并插入数据

如何在具有数百条记录的现有csv中添加新列并从数组中填充它?

如何读取 CSV、再添加两列并插入依赖于当前列的数据?

使用 group by 汇总列并存储为 MySQL 中的新列(永久)

向表中添加了新列并减慢了整个数据库的速度。为啥?

使用 ALTER TABLE 添加新列后 H2 数据库插入数据异常