在ios上查找SQLite数据库中的条目

时间:2013-05-03 14:20:58

标签: ios sqlite

我遵循了一个关于创建SQLite数据库,存储东西并找到它的教程。 我没有做的是创建界面,因为控制台日志记录可以更快。 (这也不需要其他人建立interace,但不要忘记导入库!:))

这是重要的教程: 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

1 个答案:

答案 0 :(得分:0)

NSLog中有一条findContact声明:

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

你绝对不想在失败时再次准备。您只想检索错误消息。因此它应该是:

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

如果您这样做,您将收到一条错误消息,指出SQL语句中address的拼写错误。

坦率地说,几乎每个SQLite调用都应检查其结果,如果不是SQLITE_OKSQLITE_ROWSQLITE_DONE sqlite3_step),则应报告sqlite3_errmsg

采用sqlite3_errmsg时,您会发现错误的速度更快。让SQLite准确地告诉你问题是什么!


顺便说一句,我也建议:

  1. 我还建议您不要使用stringWithFormat构建SQL语句。如果个人姓名是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将值绑定到这些?占位符,并完全取消stringWithFormatWHERE语句的SELECT子句也是如此。

  2. 我是第二个Anupdas使用FMDB的建议。它使SQLite编码更容易。