- (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(statement)永远不会返回SQLITE_OK。
答案 0 :(得分:3)
你说:
sqlite3_step(statement)永远不会返回SQLITE_OK。
正确,如果成功,则返回SQLITE_DONE
(执行插入/更新/删除查询时)。请参阅sqlite3_step documentation。
如果您没有SQLITE_DONE
,那么您应该检查sqlite3_errmsg
以确定原因。如果它的报告“的呼叫顺序库程序”的错误,这可能意味着sqlite3_prepare_v2
失败,它实际上是说,它的看到sqlite3_step
没有成功sqlite3_prepare_v2
呼叫。
所以,你也应该检查的结果,sqlite3_prepare_v2
(因为这是更频繁,问题的来源),并确保为SQLITE_OK
,如果没有,看看{{在调用sqlite3_errmsg
之前立即1}}。如果您从sqlite3_step
收到错误并忽略该错误并只调用sqlite3_prepare_v2
,则在调用sqlite3_step
之前,您将丢失可能已检查过的有意义的错误消息,从而替换有意义的错误消息使用“库程序不按顺序”错误。
这纯粹是主观臆测,但在复制数据库中给出的有关问题与其他问题,我可以打赌,在您的测试一段时间,你跑你的代码的演绎未能复制数据库,但仍继续打电话sqlite3_step
。 sqlite3_open
如果找不到空数据库,则会创建一个空数据库。因此,如果数据库为空,我不会感到惊讶,因此来自sqlite3_open
的错误消息将报告找不到该表。如果我的猜想是正确的(即sqlite3_prepare_v2
是失败的,并呼吁sqlite3_prepare_v2
报道称,该表中没有找到),我建议从你的模拟器/设备移除应用程式(以消除任何空白数据库坐在sqlite3_errmsg
文件夹中)并尝试再次运行该应用程序。如果捆绑包中的副本失败,我还要确保您的代码不会尝试打开数据库(否则您将面临再次创建空白数据库的风险)。我可能还建议您将Documents
代码替换为:
sqlite3_open
这与if (sqlite3_open_v2([databasePath UTF8String], &_database, SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK)
NSLog(@"Database opened");
类似,但如果找不到空数据库,则不会创建空白数据库。
因此,检查所有SQLite返回码并在SQL中使用sqlite3_open
占位符的例程可能如下所示:
?
将字符串值绑定到列的方法可能如下所示:
- (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);
}