2

SQLite データベースの作成、データの保存、検索に関するチュートリアルに従いました。コンソールのロギングははるかに高速になる可能性があるため、インターフェイスの作成は行いませんでした。(また、他の人がインターフェイスを構築する必要はありませんが、ライブラリをインポートすることを忘れないでください!:))

これは、問題が発生した場合のチュートリアルです: 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
4

1 に答える 1

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_DONEfor の場合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同様です。WHERESELECT

  2. FMDB を使用するという Anupdas の提案に賛成します。これにより、SQLite のコーディングがはるかに簡単になります。

于 2013-05-03T15:13:52.293 に答える