1

iPad 用の iOS 6 アプリで使用されるこの sqlite3 テーブルがあります。

CREATE TABLE notes(id INTEGER PRIMARY KEY, note TEXT, noteDate TEXT, wasUploaded INTEGER);

sqlite3 コマンド ラインから、このクエリは機能します。

sqlite> Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `wasUploaded`=0;

1|Well|2012-10-04 22:46:23|0

iOS iPad 6.0 シミュレーターでは、これらの各クエリは上記とまったく同じデータを返します。

const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `id`=1";

const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `note`='Well'";

const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `noteDate`='2012-10-04 22:46:23'";

しかし、コマンド ラインで問題なく動作していたこのクエリは、現在はデータを返しません。

const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `wasUploaded`=0";

困惑しましたか。最後のクエリが機能しないのはなぜですか? その列をインデックスか何かにする必要がありますか? 他の 2 つのインデックスのない列は機能しますが、これは機能しません。

エラーなし。データを返さない最後のクエリは通常のリターン コード 101 (sqlite3_step() の実行が終了しました) を返し、where 句のないクエリは他の 3 つのクエリと同じデータを返します。

編集:ここに完全なコードがあります

- (NSString *)getNotesToBeUploaded {
sqlite3 *stuDb;
NSString *thisNote;
NSMutableString *notes = [[NSMutableString alloc]init];

if (self.filePath == @"empty") {
    [self setDatabaseFilePath];
}

if (sqlite3_open([self.filePath UTF8String], &stuDb) == SQLITE_OK)
{
    // this is the query line that get changed to show stackoverflow the different results:
    const char *sqlStatement = "Select `id`,`note`,`noteDate` FROM notes WHERE `wasUploaded`=0";
    sqlite3_stmt *compiledStatement;
    int nResult = sqlite3_prepare_v2(stuDb, sqlStatement, -1, &compiledStatement, NULL);
    if ( nResult == SQLITE_OK)
    {
        int nret; // diagnostic used to watch return vaues when single stepping
        while ((nret = sqlite3_step(compiledStatement)) == SQLITE_ROW)
        {
            int id =  sqlite3_column_int(compiledStatement, 0);
            const unsigned char *note =  sqlite3_column_text(compiledStatement, 1);
            const unsigned char *noteDate =  sqlite3_column_text(compiledStatement, 2);
            int wu =  sqlite3_column_int(compiledStatement, 4);
            if (strlen((const char *)note) > 0 && strlen((const char *)noteDate) > 0)
            {
                thisNote = [NSString stringWithFormat:@"%d,%s,%s,%d\n",id, noteDate, note, wu];
                [notes appendString:thisNote];
            }
        }
    } else {
        sqlite3_finalize(compiledStatement);// prevent small memory leaks
        sqlite3_close(stuDb);
        thisNote =
        [NSString stringWithFormat:@"prepare failed with status:%d in %s at line %d path was %@,0,0\n",nResult,__FILE__,__LINE__,self.filePath];
        [notes appendString:thisNote];
        [notes appendString:@"\n"];
        return (NSString *)notes;
    }
    sqlite3_finalize(compiledStatement);
    sqlite3_close(stuDb);
}
4

1 に答える 1

2

通話のリターン コードを確認していsqlite3ますか? また、必要に応じてSQLITE_OKまたはが得られない場合は、結果をSQLITE_ROWチェックして何が起こっているのかを診断する必要があります。sqlite3_errmsg私たちに助けてもらいたい場合は、コードを共有する必要があります。しかし、初めての iOS SQLite アプリで最も一般的な問題は次のとおりです。

  • アプリのバンドルにデータベースが含まれていません。Target の設定を確認し、データベースが に含まれていることを確認してくださいBuild Phases~/Library/Application Support/iPhone Simulatorフォルダー内のシミュレーターでアプリのバンドルを見て、これを確認することもできます。これを行いたい場合は、ターミナルのコマンド ライン インターフェイスに~/Library入力してフォルダーを再表示することをお勧めします。chflags no hidden ~/Library

  • アプリからデータベースを更新することを計画している場合、使用を開始する前に、最初にデータベースをバンドルからDocumentsフォルダーにコピーできません。

  • sqlite3_openデータベースが正常に開かれたことの証拠として、成功した戻りコードを使用および解釈する...しかし、データベースが見つからない場合、sqlite3_open関数は迷惑なことに新しい空のデータベースを作成します...sqlite3_open_v2代わりに使用することを常にお勧めします。必要でない場合は、パラメーターを省略して、見つからない場合は空のデータベースを作成できます。

確かに、コード関連の問題 (関数が呼び出される順序、リターン コードのチェックの失敗など) も大量にある可能性があります。コードを見ずにこれ以上コメントすることはできません。

そして、iOS での SQLite プログラミングを大幅に簡素化するFMDB Objective-C SQLite ラッパー ライブラリをチェックする価値があるという、SQLite プログラミングに関する最後のアドバイスを共有する義務があると感じています。


アップデート:

あなたのコードを見ると、それはうまく見えます。NSLog私はそれを実行しました(メモを追加するのではなく、微調整しただけです):

- (void)test2
{
    sqlite3 *stuDb;
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *databaseName = [documentsDirectory stringByAppendingPathComponent:@"test.db"];

    if (sqlite3_open([databaseName UTF8String], &stuDb) == SQLITE_OK)
    {
        // this is the query line that get changed to show stackoverflow the different results:
        const char *sqlStatement = "Select `id`,`note`,`noteDate` FROM notes WHERE `wasUploaded`=0";
        sqlite3_stmt *compiledStatement;
        int nResult = sqlite3_prepare_v2(stuDb, sqlStatement, -1, &compiledStatement, NULL);
        if ( nResult == SQLITE_OK)
        {
            int nret; // diagnostic used to watch return vaues when single stepping
            while ((nret = sqlite3_step(compiledStatement)) == SQLITE_ROW)
            {
                int id =  sqlite3_column_int(compiledStatement, 0);
                const unsigned char *note =  sqlite3_column_text(compiledStatement, 1);
                const unsigned char *noteDate =  sqlite3_column_text(compiledStatement, 2);
                int wu =  sqlite3_column_int(compiledStatement, 4);
                if (strlen((const char *)note) > 0 && strlen((const char *)noteDate) > 0)
                {
                    // thisNote = [NSString stringWithFormat:@"%d,%s,%s,%d\n",id, noteDate, note, wu];
                    // [notes appendString:thisNote];
                    NSLog(@"%d,%s,%s,%d\n",id, noteDate, note, wu);
                }
            }
        } else {
            //sqlite3_finalize(compiledStatement);// prevent small memory leaks, not needed if the prepare failed
            sqlite3_close(stuDb);
            NSLog(@"prepare failed with error %s", sqlite3_errmsg(stuDb));
            return;
        }
        sqlite3_finalize(compiledStatement);
        sqlite3_close(stuDb);
    }
}

そして、私は結果を得ました:

2012-10-05 15:44:06.075 test8[1574:c07] 1,2012-10-05 19:43:37,ABC,0
2012-10-05 15:44:06.076 test8[1574:c07] 2,2012-10-05 19:43:46,XYZ,0

したがって、問題はデータベース自体にあるはずです。あなたの最後のコメントから判断すると、データベースの再構築があなたのためにそれを行ったようです。それは素晴らしいことです。

于 2012-10-05T18:33:23.237 に答える