2012-05-03 103 views
2

如何在sqlite iPhone中插入数据到表中?将数据插入SQLite数据库的正确方法iPhone

我尝试以下,但它的失败:

NSString *query=[NSString stringWithFormat:@"insert into %@ (name) values ('%@')", table name,myName ]; 


sqlite3 *database; 

sqlite3_stmt *createStmt = nil; 

if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { 
    if (createStmt == nil) { 

     if (sqlite3_prepare_v2(database, [query UTF8String], -1, &createStmt, NULL) != SQLITE_OK) { 
      return NO; 
     } 
     sqlite3_exec(database, [query UTF8String], NULL, NULL, NULL); 
     return YES; 
    } 

    return YES; 
}else { 
    return NO; 
} 

我已经创建表方式如下:

create table if not exists myDets (dets_id integer primary key asc, name text); 

我也使用Firefox的SQLite插件检查分贝。当我尝试通过插入记录的Firefox在我的分贝它给了我以下错误:

Failed to insert values 
Exception Name: NS_ERROR_STORAGE_IOERR 
Exception Message: Component returned failure code: 0x80630002 (NS_ERROR_STORAGE_IOERR)  [mozIStorageStatement.execute] 

严重卡住:(

而且,我是在iPhone模拟器运行此,这很重要

请帮助

在此先感谢。

回答

3
  • 使用参数,也没有字符串格式您的UPDATE
  • 添加大量的跟踪,检查返回码和检查错误代码(你问的问题不清楚是什么错误,你在iPhone上遇到的问题)。
  • 使用sqlite3_errmsg获取错误消息
  • 构建您的dbPath并将其注销。确保您可以在模拟器下从终端打开数据库。请记住,sqlite将被动地在内存中创建一个数据库,所以如果你的路径是关闭的,并且数据库不存在,可能会令人困惑。
  • 打印出您的更新声明,并从您登录的路径中的终端中的sqlite cmdline应用程序尝试它。
  • 如果您要将数据库放入主包资源中,它是一个模板,需要复制才能打开并写入该模板。

下面是我的一个样本的更新功能:

- (void)updateContact: (Contact*)contact error:(NSError**)error 
{ 
    if (![self ensureDatabaseOpen:error]) 
    { 
     return; 
    } 

    NSLog(@">> ContactManager::updateContact"); 

    // prep statement 
    sqlite3_stmt *statement; 
    NSString *querySQL = @"update contacts set name=?,address=?,phone=? where id=?"; 
    NSLog(@"query: %@", querySQL); 
    const char *query_stmt = [querySQL UTF8String]; 

    // preparing a query compiles the query so it can be re-used. 
    sqlite3_prepare_v2(_contactDb, query_stmt, -1, &statement, NULL);  
    sqlite3_bind_text(statement, 1, [[contact name] UTF8String], -1, SQLITE_STATIC); 
    sqlite3_bind_text(statement, 2, [[contact address] UTF8String], -1, SQLITE_STATIC); 
    sqlite3_bind_text(statement, 3, [[contact phone] UTF8String], -1, SQLITE_STATIC); 
    sqlite3_bind_int64(statement, 4, [[contact id] longLongValue]); 

    NSLog(@"bind name: %@", [contact name]); 
    NSLog(@"bind address: %@", [contact address]); 
    NSLog(@"bind phone: %@", [contact phone]); 
    NSLog(@"bind int64: %qi", [[contact id] longLongValue]); 

    // process result 
    if (sqlite3_step(statement) != SQLITE_DONE) 
    { 
     NSLog(@"error: %s", sqlite3_errmsg(_contactDb)); 
    } 

    sqlite3_finalize(statement); 
} 

在示例中,DB是资源复制到一个路径并打开。下面是确保打开功能我使用这样做:

- (BOOL)ensureDatabaseOpen: (NSError **)error 
{ 
    // already created db connection 
    if (_contactDb != nil) 
    { 
     return YES; 
    } 

    NSLog(@">> ContactManager::ensureDatabaseOpen");  
    if (![self ensureDatabasePrepared:error]) 
    { 
     return NO; 
    } 

    const char *dbpath = [_dbPath UTF8String]; 
    if (sqlite3_open(dbpath, &_contactDb) != SQLITE_OK && 
     error != nil) 
    { 
     *error = [[[NSError alloc] initWithDomain:@"ContactsManager" code:1000 userInfo:nil] autorelease]; 
     return NO; 
    } 

    NSLog(@"opened"); 

    return YES; 
} 

- (BOOL)ensureDatabasePrepared: (NSError **)error 
{ 
    // already prepared 
    if ((_dbPath != nil) && 
     ([[NSFileManager defaultManager] fileExistsAtPath:_dbPath])) 
    { 
     return YES; 
    } 

    // db in main bundle - cant edit. copy to library if !exist 
    NSString *dbTemplatePath = [[NSBundle mainBundle] pathForResource:@"contacts" ofType:@"db"]; 
    NSLog(@"%@", dbTemplatePath); 

    NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject]; 
    _dbPath = [libraryPath stringByAppendingPathComponent:@"contacts.db"]; 

    NSLog(@"dbPath: %@", _dbPath); 

    // copy db from template to library 
    if (![[NSFileManager defaultManager] fileExistsAtPath:_dbPath]) 
    { 
     NSLog(@"db not exists"); 
     NSError *error = nil; 
     if (![[NSFileManager defaultManager] copyItemAtPath:dbTemplatePath toPath:_dbPath error:&error]) 
     { 
      return NO; 
     } 

     NSLog(@"copied"); 
    }  

    return YES;  
} 
+0

感谢bryanmac,会尝试... – iOSDev

+0

太好了!它也适用于我。 –

3
- (NSString *) getDBPath { 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES); 
    NSString *documentsDir = [paths objectAtIndex:0]; 
    return [documentsDir stringByAppendingPathComponent:@"iHadDB.sqlite"]; 
} 

- (void) insertValueToDatabase { 

    NSString *dbPath =[self getDBPath]; 

    NSString *select_Meal = dummy_select_Meal; 
    NSString *dateTime = dummy_date_Time; 
    NSString *location = dummy_location; 
    NSString *mealItem = dummy_mealItem; 

    if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) { 

     const char *sqlDB = "Insert into iHad(Mealtype,DateAndTime,Location,Mealitem) VALUES (?,?,?,?)"; 

     if(sqlite3_prepare_v2(database, sqlDB, -1, &addStmt, NULL) != SQLITE_OK) 
      NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database)); 

     sqlite3_bind_text(addStmt, 1, [select_Meal UTF8String], -1, SQLITE_TRANSIENT); 
     sqlite3_bind_text(addStmt, 2, [dateTime UTF8String], -1, SQLITE_TRANSIENT); 
     sqlite3_bind_text(addStmt, 3, [location UTF8String], -1, SQLITE_TRANSIENT); 
     sqlite3_bind_text(addStmt, 4, [mealItem UTF8String], -1, SQLITE_TRANSIENT); 

     if(SQLITE_DONE != sqlite3_step(addStmt)) 
      NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database)); 
     //else 
      //SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid 
      //coffeeID = sqlite3_last_insert_rowid(database); 

     //Reset the add statement. 
     sqlite3_reset(addStmt); 

    } 
    else 
     sqlite3_close(database); 

}