2012-05-10 16 views
5

Estoy tratando de 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 sintaxis 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.Creación de un archivo de base de datos SQLite3 a través de Objective-C

Recapitulación: 1. ¿Cuál es la sintaxis 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, consigo 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 cualquiera que se tome el tiempo para explicar parte de esta cosas, ya que soy muy nuevo y no he tenido éxito en lograr algunas de las cosas que he intentado. ¡Muchísimas gracias por la ayuda!

Respuesta

2

sqlite es una pena 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 sqlite buenos y fáciles de usar para el objetivo c. Te sugiero que uses uno de esos.

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

editar: el único lugar donde puedes escribir cosas en tu aplicación está en el directorio de documentos ... así que ... términos sencillos ... si el archivo de datos no está en el directorio de documentos ... es de solo lectura ... también ... cuando lee/escribe en su db ... el SO copia el db en el directorio de documentos ... y hace toda la lectura y escritura allí para que pueda tener un db en su paquete de aplicaciones pero no puede editar ese ... así que terminarás con 2 db.Tuve el mismo problema yo mismo ... y lo arreglé fusionando los 2 db cuando actualicé la aplicación

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

+0

Esto fue realmente útil, pero esperaba evitar cualquier tipo de envoltorios o bibliotecas externas. Voy a esperar otras respuestas para ver si alguien podría proporcionar alguna información sobre cómo sería la sintaxis de creación de tabla pura. Todo lo que estoy pasando en mi aplicación no está yendo bien, jaja. ¡Gracias por la respuesta rápida! – Skizz

+0

, así es su decisión ... pero tenga en cuenta que al usar los envoltorios solo tendrá que usar llamadas objetivas c ... como [self getRow: 2]. Es MUCHO más fácil que pasar por todas las llamadas sql: abra db, haga una declaración, ejecute la instrucción, luego vea si no es nula, maneje el error, procese los datos, y luego cierre. Eso es un dolor solo por escribir. – skytz

0

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

continuación sqlite3 tblStore.sqlite

a continuación, utilizar .schema tblStore debe mostrar su mesa esquema 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.

0

¿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 veces se describe como que tiene una curva de aprendizaje. 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.

+0

Mi empleador está interesado en usar SQLite ya que es compatible con iOS. No tuve mucha información sobre ese asunto. Sin embargo, su explicación de Sandbox/Documents fue perfecta para mí. Realmente me faltaba entendimiento en esa área. Si no le importa, ¿podría entrar en mayor detalle (o dirigirme a un recurso) para explicar cómo acceder a mi zona de pruebas, y más específicamente al directorio de documentos ubicado dentro de mi zona de pruebas? Realmente aprecio la respuesta rápida. ¡Muchas gracias! – Skizz

2

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; 
+0

Si creo mi ruta de esta manera: NSArray * paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString * documentsDirectory = [paths lastObject]; Entonces podría simplemente pasar "documentsDirectory" al método, ¿correcto? – Skizz

+0

Sí, eso es correcto. –

11

// 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 Tabla

-(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"); 
    } 
} 

// registros Inserción

-(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 llamar 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 nombre de usuario y la contraseña se NSString valores;

+0

no está creando la base de datos, está creando una tabla en un db existente – OMGPOP

+3

el código es incorrecto (no creó un archivo .sqlite en el directorio de documentos. – OMGPOP

+0

Algunos métodos se pueden considerar con el siguiente tutorial: http: // www .appcoda.com/sqlite-database-ios-app-tutorial/ –

0

Quizás olvidó Table Insertions. Base de datos y tabla creadas pero su tabla vacía. tratando de leer los registros de la Tabla que está vacía.

+0

Trate de insertar algunos registros y Read.hope resolverá su problema. – Baalu

Cuestiones relacionadas