sqlite_prepare_v2不返回SQLITE_OK

问题描述 投票:1回答:2

我一直在试图挽救高分到数据库,并已经发生故障许多过去的一周,我不知道为什么它不工作。我不断收到“问题的准备声明”,并拒绝插入到信息数据库。我曾与数据库管理器检查,以确保没有与SQL语句中的错字,当查询的管理器上运行,它工作正常 - 这只是竟然放弃了我的问题iphone。如果任何人都可以请尽快查看,并看到一些不妥之处,可以让我知道,我将不胜感激!

- (NSMutableArray *) saveLocal {
    NSLog(@"save local database");
    @try {
        [self checkDB];
        sqlite3_stmt *sqlStatement2;


        NSString *sqlS = [NSString stringWithFormat:@"INSERT INTO localHighscore (difficulty, score, uname, puzzles, multiplier, oneshots, hints) VALUES (%i,%i,\"%@\",%i,%i,%i,%i)",[[MySingleton sharedMySingleton] goDifficulty],[[MySingleton sharedMySingleton] goScore],_player, [[MySingleton sharedMySingleton] goPuzzles], [[MySingleton sharedMySingleton] goMultiplier], [[MySingleton sharedMySingleton] goOneshots], [[MySingleton sharedMySingleton] goHints]];
        NSLog(@"%@",sqlS);
        const char *sql = [sqlS UTF8String];


        if(sqlite3_prepare_v2(localHighscore, sql, -1, &sqlStatement2, NULL) == SQLITE_OK)
        {
            sqlite3_step(sqlStatement2);
            sqlite3_reset(sqlStatement2);
            sqlite3_finalize(sqlStatement2);
            NSLog(@"save complete");
        } else {
            NSLog(@"Problem with prepare statement");
        }  
        sqlite3_close(localHighscore);
    }@catch (NSException *exception) {
        NSLog(@"An exception occured: %@", [exception reason]);
    }@finally{
        NSLog(@"DB Loaded!");
    }
}

这里是CHECKDB方法,检查是否存在数据库,并创建一个,如果它不

- (void)checkDB {
    NSString *docsDir;
    NSArray *dirPaths;

    // Get the documents directory
    dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    docsDir = [dirPaths objectAtIndex:0];

    // Build the path to the database file
    databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"localHighscore.sqlite"]];

    NSFileManager *filemgr = [NSFileManager defaultManager];    
    if ([filemgr fileExistsAtPath: databasePath ] == NO)
    {
    const char *dbpath = [databasePath UTF8String];
        NSLog(@"file was not found");
        if (sqlite3_open(dbpath, &localHighscore) == SQLITE_OK)
        {
            NSLog(@"db open");
            char *errMsg;
            const char *sql_stmt = "CREATE TABLE IF NOT EXISTS localHighscore(pk INTEGER PRIMARY KEY AUTOINCREMENT, difficulty TINYINT, score MEDIUMINT, uname VARCHAR(255), puzzles TINYINT, multiplier TINYINT, oneshots TINYINT, hints TINYINT)";

            if (sqlite3_exec(localHighscore, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
            {
                NSLog(@"Failed to create table");
            }
            sqlite3_close(localHighscore);            
        } else {
            NSLog(@"Failed to open/create database");
        }
    }
    [filemgr release];
}

先谢谢您的帮助!

objective-c database sqlite prepare
2个回答
3
投票

一对夫妇的想法:

  1. 你似乎没有试图使用数据库之前调用sqlite3_open
  2. 每当你得到一个错误,你应该看看sqlite3_errmsg,例如 if (sqlite3_exec(localHighscore, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) { NSLog(@"Failed to create table: %s", sqlite3_errmsg(localHighscore)); }
  3. 也许无关你的问题,但使用stringWithFormat一般情况下不应建立一个SQL语句(至少如果您有任何文本字段)。使用?占位符的SQL,然后用sqlite3_bind_xxx功能。 const char *sql = "INSERT INTO localHighscore (difficulty, score, uname, puzzles, multiplier, oneshots, hints) VALUES (?,?,?,?,?,?,?)"; if(sqlite3_prepare_v2(localHighscore, sql, -1, &sqlStatement2, NULL) == SQLITE_OK) { if (sqlite3_bind_int(sqlStatement2, 1, [[MySingleton sharedMySingleton] goDifficulty]) != SQLITE_OK) { NSLog(@"bind 1 failed: %s", sqlite3_errmsg(localHighscore)); } if (sqlite3_bind_int(sqlStatement2, 2, [[MySingleton sharedMySingleton] goScore]) != SQLITE_OK) { NSLog(@"bind 2 failed: %s", sqlite3_errmsg(localHighscore)); } if (sqlite3_bind_text(sqlStatement2, 3, [_player UTF8String], -1, NULL) != SQLITE_OK) { NSLog(@"bind 3 failed: %s", sqlite3_errmsg(localHighscore)); } // repeat this bind process for each variable if (sqlite3_step(sqlStatement2) != SQLITE_DONE) { NSLog(@"step failed: %s", sqlite3_errmsg(localHighscore)); } // reset not needed (doesn't hurt, but not needed unless you're going to re-use it // sqlite3_reset(sqlStatement2); sqlite3_finalize(sqlStatement2); NSLog(@"save complete"); } else { NSLog(@"Problem with prepare statement: %s", sqlite3_errmsg(localHighscore)); } sqlite3_close(localHighscore); 如果你觉得这句法笨重,那么也许可以考虑使用FMDB,从而简化您的SQL互动。但要十分警惕stringWithFormat与SQL(如果插入的字符串有引号,则sqlite3_prepare会失败,从理论上说,您的应用程序受到SQL注入攻击等)。
  4. 顺便说一句,你不应该[filemgr release],因为你不拥有它。

0
投票

我看到“sqlite3_prepare_v2()”功能,当SQL语句包含像“booleanfield =假”,而不是“booleanfield = 0”的条件下返回“一般错误”(错误代码= 1)。在SQLiteStudio程序的SQL执行箱相同的SQL语句中使用漠然第一或比较的第二种形式提供了良好的效果。

© www.soinside.com 2019 - 2024. All rights reserved.