Cómo insert todos los valores nuevos en la misma fila para cada session en sqlite (para iOS)

No puedo entender este problema de database por completo.

Antes que nada, ¿debería abrir mi connection de db desde el principio y mantenerla abierta hasta que la aplicación entre en segundo plano? ¿O debería abrirla y cerrarla cada vez que inserte una nueva?

Mi método de connection abierta

NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [docPaths objectAtIndex:0]; NSString *dbPath = [documentsDir stringByAppendingPathComponent:@"insider.sqlite"]; FMDatabase *database = [FMDatabase databaseWithPath:dbPath]; [database open]; [database executeUpdate:@"create table if not exists userInfo (device_token text primary key, device_type text, carrier text, app_version text,os_version text, first_name text, last_name text,last_viewed_item text, last_added_item text, last_item_price_tag text, name_entenetworking integer, login_screen integer, item_detailed_screen integer,item_selected integer )"]; // [database close]; 

empiezo la aplicación con este método (en appDelegate applicationDidFinishLauch) pero durante la session quiero save todos mis datos nuevos en la misma fila.

pero con estos methods que estoy usando

 -(void)getUserFirstName:(NSString *)firstName { NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [docPaths objectAtIndex:0]; NSString *dbPath = [documentsDir stringByAppendingPathComponent:@"insider.sqlite"]; FMDatabase *database = [FMDatabase databaseWithPath:dbPath]; [database open]; [database executeUpdate:@"INSERT INTO userInfo (first_name) VALUES (?)",firstName]; [database close]; } 

y mi otro método

 -(void)getUserLastName:(NSString *)lastname { NSLog(@"soyisim giriliyo"); NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [docPaths objectAtIndex:0]; NSString *dbPath = [documentsDir stringByAppendingPathComponent:@"insider.sqlite"]; FMDatabase *database = [FMDatabase databaseWithPath:dbPath]; [database open]; [database executeUpdate:@"INSERT INTO userInfo (last_name) VALUES (?)",lastname]; [database close]; } 

pero cuando los guardo y trato de recogerlos, tengo esto

 2014-09-07 20:26:08.522 PushChat[2974:60b] first Name: Frank lastname: (null) 2014-09-07 20:26:08.522 PushChat[2974:60b] first Name:: (null) lastname: Jemmyson 2014-09-07 20:26:08.522 PushChat[2974:60b] first Name: george lastname: (null) 2014-09-07 20:26:08.522 PushChat[2974:60b] first Name: (null) lastname: herose 

obtengo valores de campo para cada fila.

Traté de cambiar mi método de creación de tabla y agregué id integer primary key, pero durante la otra inserción no pude hacer un seguimiento de esta identificación de session y no pensé que fuera buena para el performance.

Entonces, ¿se supone que debo hacer esto bien? Tengo un total de 13 campos y algunos de ellos pueden ser nulos, pero durante una session todos ellos deben estar en la misma línea.

Gracias por adelantado

Un par de pensamientos:

  1. ¿Por qué tienes dos methods para insert el nombre y apellido? ¿Lo necesitas? ¿Alguna razón por la que no haces eso en una sola statement SQL?

  2. Asumiendo por un segundo que debe hacerlo en declaraciones separadas como esta, la primera debe ser INSERT y la segunda statement SQL debe ser UPDATE .

  3. Si lo desea, SQLite puede realizar un seguimiento del identificador único de la fila por usted. Por lo tanto, agregue una columna llamada user_info_id integer primary key autoincrement . Luego, inmediatamente después de insert sus datos, mire la [database lastInsertRowId] , y eso le devolverá el valor generado automáticamente para su columna user_info_id .

    Entonces, volviendo al punto anterior, insertía una fila con el primer nombre, recuperaría inmediatamente el lastInsertRowId , y luego usaría eso como un parámetro para la cláusula WHERE en su instrucción UPDATE donde establece el apellido, por ej.

     success = [database executeUpdate:@"UPDATE userInfo SET last_name = ? WHERE user_info_id = ?", lastName, @(rowIdValue)]; 

    Tenga en count que ese valor para el user_info_id se almacena presumiblemente en una variable sqlite_int64 (por ejemplo, el valor devuelto por el lastInsertRowId método lastInsertRowId ), por lo que cuando lo utiliza en una llamada a executeUpdate , NSNumber un NSNumber enrollándolo con un @(rowIdValue) .

  4. Mientras que FMDB te ahorra muchos dolores de cabeza con valores bindings para columnas y cosas por el estilo, aún deberías estar revisando los valores de retorno (generalmente un valor BOOL en FMDB). Si falló, log [database lastErrorMessage] .

  5. No abra y cierre la database para cada instrucción SQL. Abra la database una vez y déjela abierta. Automáticamente confirma las INSERT / UPDATE medida que las realiza, por lo que es muy robusto.

Si entendí bien su problema, desea crear una nueva input en su database con cada nueva session. Así que simplemente déle a su session una identificación (es decir, un número random) y manténgala almacenada en algún lugar de su aplicación. Si la ID ya existe en su Base de datos, elija una nueva. Si no, inserte una nueva fila. Su ID debe ser la key principal.

Entonces, todos los valores son nulos, excepto la ID. Si desea agregar / cambiar valores para esta identificación específica, solo ejecute algo como esto:

 NSString *sql = [NSString stringWithFormat:@"UPDATE userInfo SET last_name = \"%@\" WHERE id = %@", lastname, uniqueSessionID]; 

PD: Sí, debes abrir y cerrar la connection cada vez que la uses y no mantenerla abierta todo el time. Una connection abierta requiere resources que podrían usarse en otro lugar.