Objective c FMDB:添加新列并插入数据

Objective c FMDB:添加新列并插入数据,objective-c,sqlite,fmdb,Objective C,Sqlite,Fmdb,在我的应用程序中,我正在使用FMDatabase。我试图将新的列添加到现有的表,然后在该列中插入数据。当我通过altertable添加列时,我没有收到任何错误,但是当我尝试在表中插入数据时,我收到错误,抱怨新添加的列不存在 这是我的密码 NSString *databasePath = [myDB getPlacesDBPath]; FMDatabase *db = [FMDatabase databaseWithPath:databasePath]; if (![db open]) {

在我的应用程序中,我正在使用
FMDatabase
。我试图将新的
添加到现有的
,然后在该列中插入
数据。当我通过
altertable
添加列时,我没有收到任何错误,但是当我尝试在表中插入数据时,我收到错误,抱怨新添加的列不存在

这是我的密码

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}

有什么问题吗?如何知道为什么不添加新列?

我在上面的简化代码示例中看不到任何东西可以解释您报告的错误。问题可能存在于其他地方(或者,在简化代码示例的过程中,您消除了问题的根源)

话虽如此,我还是有一些反应:

  • 你说:

    我试图将这个查询的结果设置为“BOOL Success”并打印结果,结果是肯定的

    我不知道怎么可能,因为
    executeQuery
    返回的是
    FMResultSet
    而不是
    BOOL
    。不过,这是没有意义的,因为您的
    altertable
    语句应该使用
    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];
    
    由于我不知道是什么导致了您描述的问题,我只能建议您在调试器中单步执行此代码,并确保它遵循您认为的路径。

    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()
    
    可能有人需要帮助。
    继续编码..

    问题在于-[FMDatabase executeQuery:]不执行提交的指令,它只准备语句

    要执行它们,您需要执行“步骤”

    在FMDB中,由-[FMResultSet next]在内部通过调用sqlite3_步骤()完成

    因为-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"];
    

    谢谢你清晰、有条理、简单的回答。我不知道到底是什么问题,但使用executeUpdate而不是executeQuery解决了问题。