2013-05-03 3 views
2

Я последовал за учебником о создании базы данных SQLite, хранении и поиске. Что я не делал, так это создание интерфейса, поскольку ведение журнала консоли может быть намного быстрее. (который также не требует для других людей, чтобы построить interace, но не забудьте импортировать библиотеку! :))найти запись в базе данных SQLite на ios

Это учебник для упаковывают это важно: http://www.techotopia.com/index.php/An_Example_SQLite_based_iOS_6_iPhone_Application

У меня есть проблема с поиском данных, кто-то знает, что это может быть?

- (void) findContact { 
    const char *dbpath = [_databasePath UTF8String]; 
    sqlite3_stmt *statement; 

    if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) { 

     NSString *querySQL = [NSString stringWithFormat: 
           @"SELECT adress, phone FROM contacts WHERE name=\"%@\"", @"DoekeW"]; 

     const char *query_stmt = [querySQL UTF8String]; 

     if(sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK) { 
      if(sqlite3_step(statement) == SQLITE_ROW) { 
       NSString *adressField = [[NSString alloc] initWithUTF8String: 
             (const char*) sqlite3_column_text(statement, 0)]; 
       NSString *phoneField = [[NSString alloc] initWithUTF8String: 
             (const char*) sqlite3_column_text(statement, 1)]; 
       NSLog(@"adressField: %@ phoneField: %@", adressField, phoneField); 
      } 
      else { 
       NSLog(@"no match"); 
      } 
      sqlite3_finalize(statement); 
     } 
     else { 
      // 1, whatever that is 
      NSLog(@"hmm %d", sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL)); 
     } 
     sqlite3_close(_contactDB); 
    } 
} 

здесь полный код:

.h файл:

#import <UIKit/UIKit.h> 
#import <sqlite3.h> 

@interface IGViewController : UIViewController 

@property (strong, nonatomic) NSString *databasePath; 
@property (nonatomic) sqlite3 *contactDB; 

@end 

.m файл

#import "IGViewController.h" 

@interface IGViewController() 

@end 

@implementation IGViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 

    NSString *docsDir; 
    NSArray *dirPaths; 

    // Get the documents directory 
    dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

    docsDir = dirPaths[0]; 

    // Build the path to the database file 
    _databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"contacts.db"]]; 

    NSLog(@"%@", _databasePath); 

    NSFileManager *filemgr = [NSFileManager defaultManager]; 

    if ([filemgr fileExistsAtPath: _databasePath] == NO) { 

     const char *dbpath = [_databasePath UTF8String]; 

     if(sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) { 
      char *errMsg; 
      const char *sql_stmt = 
      "CREATE TABLE IF NOT EXISTS CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, ADDRESS TEXT, PHONE TEXT)"; 

      if (sqlite3_exec(_contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) 
      { 
       //_status.text = @"Failed to create table"; 
       NSLog(@"Failed to create table"); 

      } 
      sqlite3_close(_contactDB); 
     } else { 
      // _status.text = @"Failed to open/create database"; 
      NSLog(@"Failed to open/create database"); 
     } 
    } 

    else { 
     NSLog(@"database allready existed"); 
    } 

    [self saveData]; 

    [self findContact]; 
} 


- (void) saveData { 
    sqlite3_stmt *statement; 
    const char *dbpath = [_databasePath UTF8String]; 

    if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) { 
     NSString *insertSQL = [NSString stringWithFormat: 
           @"INSERT INTO CONTACTS (name, address, phone) VALUES (\"%@\", \"%@\", \"%@\")", 
           @"DoekeW", @"Molenstraat", @"483577"]; 

     const char *insert_stmt = [insertSQL UTF8String]; 
     sqlite3_prepare_v2(_contactDB, insert_stmt, -1, &statement, NULL); 
     if(sqlite3_step(statement) == SQLITE_DONE) { 
      NSLog(@"saved data!"); 
     } 
     else { 
      NSLog(@"something wrong, no data saved"); 
     } 
     sqlite3_finalize(statement); 
     sqlite3_close(_contactDB); 
    } 
} 

- (void) findContact { 
    const char *dbpath = [_databasePath UTF8String]; 
    sqlite3_stmt *statement; 

    if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) { 

     NSString *querySQL = [NSString stringWithFormat: 
           @"SELECT adress, phone FROM contacts WHERE name=\"%@\"", @"DoekeW"]; 

     const char *query_stmt = [querySQL UTF8String]; 

     if(sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK) { 
      if(sqlite3_step(statement) == SQLITE_ROW) { 
       NSString *adressField = [[NSString alloc] initWithUTF8String: 
             (const char*) sqlite3_column_text(statement, 0)]; 
       NSString *phoneField = [[NSString alloc] initWithUTF8String: 
             (const char*) sqlite3_column_text(statement, 1)]; 
       NSLog(@"adressField: %@ phoneField: %@", adressField, phoneField); 
      } 
      else { 
       NSLog(@"no match"); 
      } 
      sqlite3_finalize(statement); 
     } 
     else { 
      // 1, whatever that is 
      NSLog(@"hmm %d", sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL)); 
     } 
     sqlite3_close(_contactDB); 
    } 
} 



- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 
+0

Я бы порекомендовал вам попробовать FMDB, гораздо проще работать с sqlite, и у них есть подспец для cocoapods, поэтому настройка будет ветерок. Отличный [учебник по использованию FMDB] (http://www.highoncoding.com/Articles/836_Persisting_iOS_Application_Data_in_SQLite_Database_Using_FMDB.aspx) – Anupdas

ответ

0

У вас есть NSLog заявление в findContact, который говорит:

NSLog(@"hmm %d", sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL)); 

Вы определенно не хотите снова готовиться к сбоям. Вы просто хотите получить сообщение об ошибке. Таким образом, это должно быть:

NSLog(@"prepare failed: %s", sqlite3_errmsg(_contactDB)); 

Если вы сделали это, вы получили сообщение об ошибке, что указал на орфографические ошибки в address в вашем SQL заявление.

Честно говоря, практически каждый SQLite вызов должен проверить свой результат, и если не SQLITE_OK (или SQLITE_ROW или SQLITE_DONE для sqlite3_step) должны сообщить sqlite3_errmsg.

Вы найдете свои ошибки гораздо быстрее, когда принимаете sqlite3_errmsg. Пусть SQLite точно скажет вам, в чем проблема!


Как и в сторону, я бы также предложить:

  1. Я также советую вам с когда-либо строить SQL заявление с stringWithFormat. У вас возникнет проблема, если имя человека было, например, Dwayne "The Rock" Johnson. Скорее, вы должны использовать ? заполнители. (Вы также будете подвержены атакам SQL-инъекции.) Практический результат, а не:

    NSString *insertSQL = [NSString stringWithFormat: 
             @"INSERT INTO CONTACTS (name, address, phone) VALUES (\"%@\", \"%@\", \"%@\")", 
             @"DoekeW", @"Molenstraat", @"483577"]; 
    
    const char *insert_stmt = [insertSQL UTF8String]; 
    sqlite3_prepare_v2(_contactDB, insert_stmt, -1, &statement, NULL); 
    if(sqlite3_step(statement) == SQLITE_DONE) { 
        NSLog(@"saved data!"); 
    } 
    else { 
        NSLog(@"something wrong, no data saved"); 
    } 
    sqlite3_finalize(statement); 
    

    вы должны использовать:

    const char *insert_stmt = "INSERT INTO CONTACTS (name, address, phone) VALUES (?, ?, ?)"; 
    
    if (sqlite3_prepare_v2(_contactDB, insert_stmt, -1, &statement, NULL) != SQLITE_OK) 
        NSLog(@"%s: prepare error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB)); 
    
    if (sqlite3_bind_text(statement, 1, [@"DoekeW" UTF8String], -1, NULL) != SQLITE_OK) 
        NSLog(@"%s: bind 1 error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB)); 
    
    if (sqlite3_bind_text(statement, 2, [@"Molenstraat" UTF8String], -1, NULL) != SQLITE_OK) 
        NSLog(@"%s: bind 2 error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB)); 
    
    if (sqlite3_bind_text(statement, 3, [@"483577" UTF8String], -1, NULL) != SQLITE_OK) 
        NSLog(@"%s: bind 3 error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB)); 
    
    if(sqlite3_step(statement) == SQLITE_DONE) { 
        NSLog(@"saved data!"); 
    } 
    else { 
        NSLog(@"%s: step error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB)); 
    } 
    
    sqlite3_finalize(statement); 
    

    В основном, используют sqlite3_bind_text связать значения этих ? заполнителей и устранить stringWithFormat в целом. То же самое верно и с предложением WHERE инструкции SELECT.

  2. I второе предложение Anupdas об использовании FMDB. Это значительно упрощает кодирование SQLite.

Смежные вопросы