Crear un archivo de base de datos SQLite3 a través de Objective-C

Intento crear un archivo de base de datos SQLite3 a través de Objective-C en tiempo de ejecución. Estoy tratando de crear una tabla llamada “tblStore”. Quiero que los nombres de campo se llamen “strStoreNumber” y “strStoreReg”. Soy nuevo en iOS y SQLite, así que estoy teniendo dificultades para encontrar la syntax para realizar esto. Además de crear la tabla, quiero que la tabla creada resida NO en el paquete de la aplicación, sino que residirá / estará almacenada en algún lugar del teléfono. La tabla debe ser legible / grabable. He leído algo sobre “user sandbox” y también un “directorio de documentos”. No estoy seguro de entender la diferencia entre los dos. Idealmente, mi aplicación usaría un botón para recibir información de los campos de texto. Después de que la entrada de los campos de texto se ponga en cadenas, se verificará si mi tabla SQLite “tblStore” existe, y si no, se creará la tabla.

Para recapitular: 1. ¿Cuál es la syntax para Obj-C / SQLite para crear una tabla llamada “tblStore” con los campos “strStoreNumber” y “strStoreReg”? 2. ¿Dónde debe residir el archivo db? Necesito leer y escribir en el archivo tblStore db. 3. ¿Cuál es la diferencia entre un “sandbox de usuario” y un “directorio de documentos”?

Esto es lo que tengo actualmente:

-(IBAction)setInput:(id)sender { NSString *strStoreNumber; NSString *strRegNumber; NSString *tableName = @"tblStore"; NSString *dbStrStore = @"strStore"; NSString *dbStrReg = @"strReg"; strStoreNumber = StoreNumber.text; strRegNumber = RegNumber.text; NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString* documentsDirectory = [paths lastObject]; NSString* databasePath = [documentsDirectory stringByAppendingPathComponent:@"tblStore.sqlite"]; // NSString* databasePath = [[NSBundle mainBundle] pathForResource:@"tblStore" ofType:@"sqlite"]; if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { NSLog(@"Opened sqlite database at %@", databasePath); char *err; NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS '%@' ('%@' TEXT PRIMARY KEY, '%@' TEXT);", tableName, dbStrStore, dbStrReg]; if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK) { sqlite3_close(database); NSAssert(0, @"Table failed to create."); } //...stuff } else { NSLog(@"Failed to open database at %@ with error %s", databasePath, sqlite3_errmsg(database)); sqlite3_close (database); } NSString *querystring; // create your statement querystring = [NSString stringWithFormat:@"SELECT strStore, strReg FROM tblStore WHERE strStore = %@ AND strReg = %@;", strStoreNumber, strRegNumber]; const char *sql = [querystring UTF8String]; NSString *szStore = nil; NSString *szReg = nil; sqlite3_stmt *statement = nil; if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL)!=SQLITE_OK) //queryString = Statement { NSLog(@"sql problem occured with: %s", sql); NSLog(@"%s", sqlite3_errmsg(database)); } else { // you could handle multiple rows here while (sqlite3_step(statement) == SQLITE_ROW) { szStore = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)]; szReg = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)]; } } sqlite3_finalize(statement); lblStoreNumber.text = szStore; lblRegNumber.text = szReg; } 

Cuando ejecuto mi aplicación, obtengo los siguientes errores:

 2012-05-10 14:58:38.169 CCoDBTry[355:f803] Opened sqlite database at /Users/Matt****/Library/Application Support/iPhone Simulator/5.1/Applications/5DB7A218-A0F6- 485F-B366-91FD2F9BC062/Documents/tblStore.sqlite 2012-05-10 14:58:38.307 CCoDBTry[355:f803] sql problem occured with: SELECT strStore, strReg FROM tblStore WHERE strStore = 8053 AND strReg = 4; 2012-05-10 14:58:38.308 CCoDBTry[355:f803] no such column: strStore 

Aprecio a cualquiera que se tome el tiempo de explicar algunas de estas cosas, ya que soy muy nuevo y no he logrado realizar algunas de las cosas que probé. ¡Muchísimas gracias por la ayuda!

sqlite es un dolor si no sabes lo que estás haciendo. También tuve algunos problemas con las funciones sqlite c pero luego decidí usar sqlite wrapper.

FMDB y BWDB son envoltorios de sqlite buenos y fáciles de usar para el objective c. Te sugiero que uses uno de esos.

Tenga en cuenta que BWDB está en un tutorial de lynda.com ( este ) y si no lo encuentra en la web … deje un comentario y lo subiré a alguna parte.

editar: el único lugar donde puede escribir cosas en su aplicación está en su directorio de documentos … así que … términos sencillos … si el archivo base no está en su directorio de documentos … es de solo lectura … también … cuando usted lee / escribe en su db … el sistema operativo copia el archivo db en el directorio de documentos … y hace toda la lectura y escritura allí para que pueda tener una base de datos en su paquete de aplicaciones, pero no puede editar esa … así terminarás con 2 db. Yo mismo tuve el mismo problema … y lo solucioné fusionando los 2 db cuando actualicé la aplicación

edit2: subí el proyecto final de BWDB (tienes tu contenedor allí y proyecto para ver cómo funciona)

// Crear DB

 -(NSString *) filePath { NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentDirectory=[paths objectAtIndex:0]; return [documentDirectory stringByAppendingPathComponent:@"LoginDatabase.sql"]; } 

// Abrir DB

 -(void)openDB { if(sqlite3_open([[self filePath]UTF8String], &db) !=SQLITE_OK) { sqlite3_close(db); NSAssert(0, @"Database failed to Open"); } } 

// Crear mesa

 -(void) createTableNamed:(NSString*)tableName withField1:(NSString*) field1 withField2:(NSString*) field2 { char *err; NSString *sql=[NSString stringWithFormat:@" CREATE TABLE IF NOT EXISTS '%@'('%@' TEXT PRIMARY KEY,'%@' TEXT);",tableName,field1,field2]; if(sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err) !=SQLITE_OK) { sqlite3_close(db); NSAssert(0, @"Table failed to create"); } } 

// Insertar registros

 -(void)insertrecordIntoTable:(NSString*) tableName withField1:(NSString*) field1 field1Value:(NSString*)field1Vaue andField2:(NSString*)field2 field2Value:(NSString*)field2Value { NSString *sqlStr=[NSString stringWithFormat:@"INSERT INTO '%@'('%@','%@')VALUES(?,?)",tableName,field1,field2]; const char *sql=[sqlStr UTF8String]; sqlite3_stmt *statement1; if(sqlite3_prepare_v2(db, sql, -1, &statement1, nil)==SQLITE_OK) { sqlite3_bind_text(statement1, 1, [field1Vaue UTF8String], -1, nil); sqlite3_bind_text(statement1, 2, [field2Value UTF8String], -1, nil); } if(sqlite3_step(statement1) !=SQLITE_DONE) NSAssert(0, @"Error upadating table"); sqlite3_finalize(statement1); } 

// Recuperar datos de la tabla

 -(void)getAllRowsFromTableNamed:(NSString *)tableName { NSString *field1Str,*field2Str; NSString *qsql=[NSString stringWithFormat:@"SELECT * FROM %@",tableName]; sqlite3_stmt *statement; if(sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, nil)==SQLITE_OK) { while(sqlite3_step(statement) ==SQLITE_ROW) { char *field1=(char *) sqlite3_column_text(statement, 0); char *field2=(char *) sqlite3_column_text(statement, 1); field1Str=[[NSString alloc]initWithUTF8String:field1]; field2Str=[[NSString alloc] initWithUTF8String:field2]; NSString *str=[NSString stringWithFormat:@"%@ - %@",field1Str,field2Str]; NSLog(@"%@",str); } } 

}

En viewDidLoad llama a los métodos

 - (void)viewDidLoad { [self openDB]; [self createTableNamed:@"Login" withField1:@"USERNAME" withField2:@"PASSWORD"]; [self insertrecordIntoTable:@"Login" withField1:@"USERNAME" field1Value:username andField2:@"PASSWORD" field2Value:password]; } 

Donde el nombre de usuario y la contraseña son valores de NSString;

Puede usar el siguiente código para obtener la base de datos creada en la carpeta Documentos. Simplemente pase una ruta en la carpeta de documentos y la función copiará la base de datos sqlite en la carpeta Documentos en la ruta especificada si es necesario. A continuación, puede utilizar esta ruta para crear y consultar tablas de bases de datos.

 + (NSString*) createDatabaseIfRequiredAtPath:(NSString*)databasePath { if (databasePath == nil) return nil; NSString *path = [NSString stringWithFormat:@"%@/%@", databasePath, kMainDBName]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error = nil; if ([fileManager fileExistsAtPath:path] == NO) { // The writable database does not exist, so copy the default to the appropriate location. NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:kMainDBName ofType:nil]; BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:path error:&error]; if (!success) { NSCAssert1(0, @"Failed to create writable database file with message '%@'.", [ error localizedDescription]); return nil; } } return path; 

¿Hay alguna razón específica por la que le gustaría usar SQLLite directamente, en lugar de utilizar CoreData? CoreData usa una base de datos SQLLite pero es en sí misma una API de nivel superior, y particularmente con las vistas de tabla y demás, obtienes una gran cantidad de funcionalidad y métodos de plantillas que ya están configurados en Xcode. La definición de modelos de datos es trivial, se obtienen toneladas de código repetitivo y está todo optimizado.

http://www.raywenderlich.com/934/core-data-on-ios-5-tutorial-getting-started

CoreData a veces se describe como tener una curva de aprendizaje empinada. Estoy en desacuerdo. Si está considerando escribir SQL usted mismo en su aplicación, no tendrá ningún problema con CoreData.

El término “caja de arena” es un término abstracto para la parte del sistema de archivos del dispositivo al que su aplicación tiene acceso de lectura / escritura. El directorio “Documentos” es un directorio específico dentro de la zona de pruebas de su aplicación. Hay otros archivos en su sandbox además del directorio de documentos, pero la mayoría de las aplicaciones que guardan datos en el sistema de archivos de iOS lo hacen en el directorio de documentos.

puede abrir la terminal y el cd a / Users / Matt * * / Library / Application Support / iPhone Simulator / 5.1 / Applications / 5DB7A218-A0F6-485F-B366-91FD2F9BC062 / Documents /

luego sqlite3 tblStore.sqlite

luego use .schema tblStore debería mostrar su esquema de tabla y puede ver si fue construido correctamente.

Su base de datos debe estar en el directorio de documentos para el acceso de escritura. Si su base de datos solo fuera a leerse, nunca podría estar escrita en su paquete de aplicaciones. Una forma de lograr esto es crear su archivo database.sqlite y agregarlo al paquete y copiarlo en el directorio de documentos (si aún no existe allí) en el inicio.

tal vez te olvidaste de las Inserciones de Tabla. Base de datos y tabla creadas pero su tabla vacía. Está tratando de leer los registros de la Tabla que está vacía.