2

こんにちは、皆さん、メリークリスマス!

sqlite と fmdb をラッパーとして使用して iOS アプリを構築しています。次のSQL文を実行しようとしています:

SELECT * FROM TABLE WHERE FIELD LIKE '%text%'

UISearchBar からのテキストを使用します。

これまでのところ、私がそれを機能させる唯一の方法は、次のコードを使用することでした:

NSString *query = [NSString stringWithFormat:@"SELECT * FROM TABLE WHERE FIELD LIKE '%%%@%%'", text];
FMResultSet *results = [db executeQuery:query];

クエリコードのみを投稿していることに注意してください。それはうまくいきます。

私が欲しいのは、SQLインジェクションを避けることなので、次のようなことを試しています:

NSString *query = @"SELECT * FROM TABLE WHERE FIELD LIKE %%?%%";
FMResultSet *results = [db executeQuery:query, text];

または次のようなもの:

NSString *query = @"SELECT * FROM TABLE WHERE FIELD LIKE ?";
FMResultSet *results = [db executeQuery:query, [NSString stringWithFormat:@"%%%@%%", text]];

動作しません。like 句 ('%%?%%') を一重引用符で囲んだり、二重ではなく単一の % を使用した場合も同様です。

この問題について説明してもらえますか? どんな助けでも大歓迎です!

あけましておめでとう!

4

1 に答える 1

4

最後の試行 (引用符なし) は正しい構文です。resultsが non-かどうかを確認していますnilか? の場合nilは、エラー文字列を確認する必要があります。たとえば、これは機能します:

NSString *searchString = @"larry";
NSString *likeParameter = [NSString stringWithFormat:@"%%%@%%", searchString];
NSString *sql = @"SELECT text_column FROM test WHERE text_column LIKE ?";

FMResultSet *results = [db executeQuery:sql, likeParameter];

if (!results)
{
    NSLog(@"error: %@", [db lastErrorMessage]);
    [db close];
    return;
}

while ([results next])
{
    NSLog(@"%s: %@", __FUNCTION__, results[0]);
}

[results close];
[db close];

ところで、あなたが特別で、エンド ユーザーにパラメータを操作させたり、直観的でない応答を得たりさせたくない (そして、エンド ユーザーに独自のワイルドカード文字を適用させたくない) 場合は、次の出現をエスケープすることができます。%またはなどのワイルドカード文字。SQL 構文_を使用します。ESCAPEしたがって、エスケープ文字の定数を定義したい場合があります。

NSString * const kEscapeCharacter = @"\\";

次に、次のように SQL を作成します。

NSString *likeParameter = [NSString stringWithFormat:@"%%%@%%", [self escapedLikeParameter:searchString]];
NSString *sql = [NSString stringWithFormat:@"SELECT text_column FROM test WHERE text_column LIKE ? ESCAPE '%@'", kEscapeCharacter];

、、およびワイルドカード文字自体をescapedLikeParameterエスケープする場所。したがって:%_

- (NSString *)escapedLikeParameter:(NSString *)string
{
    NSString *escapedString;
    escapedString = [string stringByReplacingOccurrencesOfString:kEscapeCharacter
                                                                withString:[NSString stringWithFormat:@"%@%@", kEscapeCharacter, kEscapeCharacter]];
    escapedString = [escapedString stringByReplacingOccurrencesOfString:@"_"
                                                             withString:[NSString stringWithFormat:@"%@_", kEscapeCharacter]];
    return [escapedString stringByReplacingOccurrencesOfString:@"%"
                                                    withString:[NSString stringWithFormat:@"%@%%", kEscapeCharacter]];
}

/これにより、複数文字のワイルドカード文字や単一文字のワイルドカード文字を含む任意の文字列を検索できます_

于 2012-12-28T14:53:20.910 に答える