在我的应用程序中,我需要将用户保存在本地以及在线,但是当我想将用户插入其本地数据库(sqlite3)时会出现问题。
用户可以选择一个char,也是一个用户名,这是通过一个方法传递给我的dbhandler对象,如图所示。
-(BOOL) registerUser : (NSString *) username : (int) character {
sqlite3 *db;
if(sqlite3_open([dbpath UTF8String], &db) == SQLITE_OK)
{
NSString *formatetStmt = [NSString stringWithFormat:@"INSERT INTO user VALUES (null, '%@', %d, 0, 1, 5, 1, 1, 1, 1, 1 ,1)", username, character];
sqlite3_stmt *comstmt;
if(sqlite3_prepare_v2(db, [formatetStmt UTF8String], -1, &comstmt, NULL) == SQLITE_OK)
{
sqlite3_finalize(comstmt);
if(sqlite3_step(comstmt) == SQLITE_DONE) {
NSLog(@"SUCCESS");
sqlite3_finalize(comstmt);
return YES;
}
else {
NSLog(@"NO SUCCES");
return NO;
}
sqlite3_reset(comstmt);
}
}
NSAssert1(0, @"addMyObjectIntoDatabase: failed to prepare statement with err '%s'", sqlite3_errmsg(db));
NSLog(@"FAIL");
sqlite3_close(db);
return NO;
}
}
当我执行的代码时,它表示NO SUCCESS,但是我没有收到错误,并且没有任何内容添加到数据库中。
阿米在这里做错了什么?
答案 0 :(得分:1)
SQLite是一个C
库,不适合直接使用,我建议使用Objective-C包装器,例如FMDB甚至Core Data。
以下是您的示例中的一些问题。
除非打开数据库或准备语句失败,否则永远不会关闭数据库
您应该使用?
绑定用户名和字符,以防止SQL注入而不是格式化字符串。
您正在使用它之前完成声明。在关闭数据库之前完成语句后,将完成结束。
您不知道错误代码,因为您没有从sqlite3_step
存储它是一个int。
您正在提前返回该方法而不关闭数据库。你应该设置一个成功标志,然后确保你的数据库实际打开,然后关闭它然后在结尾处返回标志。
-(BOOL) registerUser : (NSString *) username : (int) character {
//If using the same database for more operations often you may want to just keep
//the db open in a centralized location while the app is running
sqlite3 *db;
if(sqlite3_open([dbpath UTF8String], &db) == SQLITE_OK)
{
//You should bind these values to prevent SQL Injection
NSString *formatetStmt = [NSString stringWithFormat:@"INSERT INTO user VALUES (null, '%@', %d, 0, 1, 5, 1, 1, 1, 1, 1 ,1)", username, character];
sqlite3_stmt *comstmt;
if(sqlite3_prepare_v2(db, [formatetStmt UTF8String], -1, &comstmt, NULL) == SQLITE_OK)
{
// You are finalizing a statement before using it move this
// to after your done with the statement
sqlite3_finalize(comstmt);
//Try int status = sqlite3_step(comstmt)
if(sqlite3_step(comstmt) == SQLITE_DONE) {
NSLog(@"SUCCESS");
sqlite3_finalize(comstmt);
return YES;
}
else {
NSLog(@"NO SUCCES");
return NO;
}
sqlite3_reset(comstmt); //<- Never gets called because of return
// statement but you should finalize here
}
}
NSAssert1(0, @"addMyObjectIntoDatabase: failed to prepare statement with err '%s'", sqlite3_errmsg(db));
NSLog(@"FAIL");
sqlite3_close(db); // <-Never gets called unless statement fails to prepare
return NO;
}