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为非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 语法的通配符,例如%or 。因此,您可能希望为转义字符定义一个常量:_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 回答