2009-01-06 15 views
12

Estoy usando SQLite3 para el desarrollo de iPhone y estoy tratando de envolver unas pocas instrucciones de inserción en una transacción. Actualmente tengo el siguiente código que funciona correctamente, sin embargo, después de leer otra pregunta en SO me di cuenta de que sería mejor tenerlos en una transacción en lugar de uno. No pude encontrar la llamada C API para comenzar y confirmar una transacción. Parte del código está en Objective-C, pero no creo que eso sea realmente relevante para la pregunta.SQLite 3 C API Transactions

- (void)saveAnimals { 
    //Insert all the animals into the zoo database 
    int i; 

    const char *sql = "insert into Animal(Zoo_ID, Animal_Num, Animal_Text) Values(?, ?, ?)"; 
    for (i = 0; i < ([[self animalArray] count] - 1); i++) { 

     if(addStmt == nil) { 
      if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK) 
       NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database)); 
     } 
     int animalNum = [[[self animalArray] objectAtIndex:i] animal_Number]; 
     NSString *animalText = [[NSString alloc] initWithString:[[[self animalArray] objectAtIndex:i] animal_Text]]; 
     sqlite3_bind_int(addStmt, 1, zoo_ID); 
     sqlite3_bind_int(addStmt, 2, animalNum);  
     sqlite3_bind_text(addStmt, 3, [animalText UTF8String], -1, SQLITE_TRANSIENT); 
     [animalText release]; 
     if(SQLITE_DONE != sqlite3_step(addStmt)) { 
      NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database)); 
     } 

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

lo que creo que es necesario hacer estarían tomando el comando sqlite3_prepare_v2 fuera del bucle, iniciar la transacción, pasar por el bucle, confirmar la transacción. Sin embargo, no estoy seguro de cuáles son las llamadas para "iniciar la transacción" y "confirmar la transacción". ¿Y todavía usaría sqlite3_step? Gracias por tu ayuda.

Respuesta

32

iniciar una transacción con: sqlite3_exec(db, "BEGIN", 0, 0, 0);

confirmar una transacción con: sqlite3_exec(db, "COMMIT", 0, 0, 0);

+6

Se podría pensar que habría una API limpia para esto ... ¿Por qué no basta con incluir una llamada sqlite3_exec_trans_begin (db) ... – klynch

+0

does 'sqlite3_exec (db," ​​BEGIN ", 0, 0, 0);' ¿alguna vez falla si se accede al archivo de la base de datos al mismo tiempo? –

+2

@afriza, BEGIN es una operación diferida. Diferido significa que no se adquieren bloqueos en la base de datos hasta que se accede por primera vez a la base de datos. Por lo tanto, con una transacción diferida, la instrucción BEGIN en sí misma no le hace nada al sistema de archivos. Los bloqueos no se adquieren hasta la primera operación de lectura o escritura. Consulte http://www.sqlite.org/lang_transaction.html para ver otras variaciones sobre BEGIN que intentan obtener bloqueos. –