iOS – SQLite插入不插入数据

- (id)init { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:@"idataBase.sqlite3"]; NSLog(@"Doc path: %@",databasePath); bool databaseAlreadyExists = [[NSFileManager defaultManager] fileExistsAtPath:databasePath]; if (!databaseAlreadyExists){ NSString *databasePathFromApp = [[NSBundle mainBundle] pathForResource:@"idataBase" ofType:@"sqlite3"]; NSLog(@"Main bundle path: %@",databasePathFromApp); [[NSFileManager defaultManager] copyItemAtPath:databasePathFromApp toPath:databasePath error:nil]; } if (sqlite3_open([databasePath UTF8String], &_database) == SQLITE_OK){ NSLog(@"Database opened"); }dd return self; } -(void) setData:(NSDictionary *)data{ NSLog(@"In Data %@",data); NSString *hostAddress = [data objectForKey:@"hostAddress"]; NSString *userName = [data objectForKey:@"userName"]; NSString *passKey = [data objectForKey:@"passKey"]; NSString *listName = [data objectForKey:@"listName"]; NSString *q = [NSString stringWithFormat:@"INSERT INTO user_info (host_name,user_name,password,text_name) VALUES (\"%@\", \"%@\", \"%@\", \"%@\")",hostAddress,userName,passKey,listName]; NSLog(@"%@",q); sqlite3_stmt *statement = NULL; const char *insertQuery = [q UTF8String]; sqlite3_prepare_v2(_database, insertQuery, -1, &statement, NULL); if(sqlite3_step(statement) == SQLITE_OK){ NSLog(@"Data Inserted"); } sqlite3_finalize(statement); sqlite3_close(_database); 

}

我正在使用上面的代码插入数据。 数据库连接在init方法中打开。 但是我不能在数据库中插入数据。 sqlite3_step(语句)永远不会返回SQLITE_OK。

你说:

sqlite3_step(语句)永远不会返回SQLITE_OK。

如果成功,则返回SQLITE_DONE (执行插入/更新/删除查询时)。 请参阅sqlite3_step文档 。

如果你没有得到SQLITE_DONE ,那么你应该检查sqlite3_errmsg来确定原因。 如果报告“库函数失序”错误,这可能意味着sqlite3_prepare_v2失败,它有效地说,它看到sqlite3_step没有成功的sqlite3_prepare_v2调用。

所以,你还应该检查sqlite3_prepare_v2的结果(因为这是更常见的问题的来源),并确保它是SQLITE_OK ,如果没有,请在调用sqlite3_step之前立即查看sqlite3_step 。 如果你从sqlite3_prepare_v2有一个错误,并且忽略这个错误并且只是调用sqlite3_step ,那么你会失去在调用sqlite3_step之前检查的有意义的错误信息,用一个叫做“不按顺序的库函数”错误代替有意义的错误信息。


这是纯粹的猜想,但考虑到您在复制数据库时遇到的其他问题,我可能会打赌,在您testing的某个时候,您运行了代码复制,但未能复制数据库,但仍然调用sqlite3_open 。 和sqlite3_open将创build一个空白的数据库,如果没有find一个。 因此,如果数据库是空的,我不会感到惊讶,因此来自sqlite3_prepare_v2的错误消息将报告没有find该表。 如果我的猜想是正确的(即sqlite3_prepare_v2失败,并调用sqlite3_errmsg报告表没有find),我build议从您的模拟器/设备删除应用程序(以删除任何空白数据库坐在Documents夹中),并尝试运行应用程序。 我也确保你的代码不会试图打开数据库,如果从包中的副本失败(否则你将冒险再次创build一个空白的数据库)。 我也可能build议用下面的代码replace你的sqlite3_open代码:

 if (sqlite3_open_v2([databasePath UTF8String], &_database, SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK) NSLog(@"Database opened"); 

这就像sqlite3_open ,但是如果没有find空数据库,这将不会创build一个空数据库。


那么,例程呢,检查所有的SQLite返回码并使用? SQL中的占位符可能如下所示:

 - (void)insertUserInfo:(NSDictionary *)dictionary { NSString *hostAddress = dictionary[@"hostAddress"]; NSString *userName = dictionary[@"userName"]; NSString *passKey = dictionary[@"passKey"]; NSString *listName = dictionary[@"listName"]; const char *sql = "INSERT INTO user_info (host_name,user_name,password,text_name) VALUES (?, ?, ?, ?)"; sqlite3_stmt *statement = NULL; if (sqlite3_prepare_v2(_database, sql, -1, &statement, NULL) != SQLITE_OK) { NSLog(@"prepare failed: %s", sqlite3_errmsg(_database)); return; } if (![self bindString:hostAddress column:1 statement:statement]) return; if (![self bindString:userName column:2 statement:statement]) return; if (![self bindString:passKey column:3 statement:statement]) return; if (![self bindString:listName column:4 statement:statement]) return; if (sqlite3_step(statement) == SQLITE_DONE) { NSLog(@"Data Inserted"); } else { NSLog(@"Insert failed: %s", sqlite3_errmsg(_database)); } sqlite3_finalize(statement); } 

将string值绑定到列的方法可能如下所示:

 - (BOOL)bindString:(NSString *)value column:(NSInteger)column statement:(sqlite3_stmt *)statement { if (value) { if (sqlite3_bind_text(statement, column, [value UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK) { NSLog(@"bind column %d to %@ failed: %s", column, value, sqlite3_errmsg(_database)); sqlite3_finalize(statement); return NO; } } else { if (sqlite3_bind_null(statement, column) != SQLITE_OK) { NSLog(@"bind column %d to null failed: %s", column, sqlite3_errmsg(_database)); sqlite3_finalize(statement); return NO; } } return YES; }