0

これは奇妙な問題です。機能する回避策を見つけましたが、コードの後半で再び現れると思われるため、その理由を理解したいと思います。私に問題を与えている方法は次のとおりです。

FMDatabase *cardDatabase // initialized elsewhere
NSString *cleanChar; // this is the sanitized query string 
NSString *cardQueryString;
int cardID;

switch ([self studyLanguage])
{
    case CSStudyLanguageMandarinTraditional:
        cardQueryString = @"SELECT rowid, * FROM trad_char WHERE search = ";
        break;

// [...other cases...]

}

cardQueryString = [cardQueryString stringByAppendingString:cleanChar];

[cardDatabase open];
FMResultSet* cardSet = [cardDatabase executeQuery:cardQueryString];

BOOL foundCard = NO;

while ([cardSet next])
{ 
    foundCard = YES;
    cardID = [cardSet intForColumn:@"rowid"];
}

[cardDatabase close];

このコードは、データベース エラーを返します。

DB Error 1: no such column: 意

ここで、「意」は cleanChar に渡す文字シーケンスで、どうやら値ではなく列として扱われているようです。ただし...クエリステップで検索文字を追加すると、次のようになります。

cardQueryString = @"SELECT rowid, * FROM trad_char WHERE search = ?";
FMResultSet* cardSet = [cardDatabase executeQuery:cardQueryString, cleanChar];

すべてがうまく機能します。

だから私は実際に問題を解決しました...しかし、私はその理由を知りたいと思っています.最後に変数。

そう: これは FMDatabase のバグですか? FMDatabase の使い方がわからないだけですか? または、コードに他の問題がありますか?

4

1 に答える 1

0

検索文字列を一重引用符 (リテラルの指定に使用) で囲んでいないため、クエリは失敗しています。したがって、この行を置き換える必要があります

cardQueryString = [cardQueryString stringByAppendingString:cleanChar];

これとともに:

cardQueryString = [NSString stringWithFormat:@"%@'%@'", cardQueryString cleanChar];

ただし、NSString メソッドを使用してクエリ文字列とクエリ引数を組み合わせてクエリを作成するのは、悪い習慣です。引数に予約文字や単語が含まれている場合や、SQL インジェクションの問題が発生するエスケープ シーケンスが含まれている場合など、いくつかの理由で問題があります。

代わりに、FMDB メソッドに適切にまとめられている SQLite のバインディング メカニズムを介して引数を提供する必要があります。したがって、「回避策」は実際には最良の方法です。

cardQueryString = @"SELECT rowid, * FROM trad_char WHERE search = ?";
FMResultSet* cardSet = [cardDatabase executeQuery:cardQueryString, cleanChar];

または配列で 1 つ以上の引数を送信します。

cardQueryString = @"SELECT rowid, * FROM trad_char WHERE search = ?";
FMResultSet* cardSet = [cardDatabase executeQuery:cardQueryString arguments:@[cleanChar]];

トム・
ベアフィートウェア

于 2012-12-19T02:42:24.507 に答える