【问题标题】:Best way to pass array of integers to sqlite for an 'IN' clause将整数数组传递给“IN”子句的 sqlite 的最佳方法
【发布时间】:2013-11-10 00:51:29
【问题描述】:

我正在实现一个基于 client_type(例如 dropbox、facebook 等)选择图像的图像 dao,如下所示:

从与提供的客户端类型列表匹配的任何启用的客户端返回结果:

//clientTypes is an array of NSNumber objects - there's an enum for each client type
- (NSArray*)listByClientTypes:(NSArray*)clientTypes
{
    __block NSArray* results;

    [[self.manager queue] inDatabase:^(FMDatabase* database)
    {
        NSMutableArray* mappedResults = [[NSMutableArray alloc] init];
        NSString* sql = @"SELECT IMAGE_ADDRESS, CLIENT_TYPE, CREATED, FK_LOCATIONS_UNIQUE_COORD, PLACE_NAME, CITY, COUNTRY, IMAGE "
            "FROM IMAGES LEFT JOIN LOCATIONS ON IMAGES.FK_LOCATIONS_UNIQUE_COORD = LOCATIONS.UNIQUE_COORD "
            "WHERE CLIENT_TYPE IN (SELECT CLIENT_TYPE FROM CLIENT_STATE WHERE ENABLED = 1) "
            "AND CLIENT_TYPE IN (%@)"; // <------- THIS IS THE LIST OF CLIENTS
        FMResultSet* resultSet = [database executeQuery:sql];
        while ([resultSet next])
        {
            [mappedResults addObject:[self extractImageFrom:resultSet]];
        }
        results = [mappedResults copy];
    }];
    return results;
}

传递“IN”子句的最佳方式是什么?

通常我会使用参数绑定(例如“?”),但我不知道如何为未知数量的参数执行此操作。这可能吗?

为了找到更好的方法,我打算将逗号分隔列表替换为 SQL 查询。 .考虑到它们只是整数,这将是非常安全的。

【问题讨论】:

标签: sql objective-c sqlite fmdb


【解决方案1】:

如果您使用的是非整数数据类型,那么使用 SQL 绑定很重要,如@MartinR 的答案here 中所述。这是为了:

  • 避免未正确转义的 SQL 引起的引号问题。
  • 避免 SQL 注入漏洞。

鉴于,在你的情况下,你有一个整数列表,你可以尝试这样的事情:

NSString *sql =
[NSString stringWithFormat:@"SELECT IMAGE_ADDRESS, CLIENT_TYPE, CREATED, FK_LOCATIONS_UNIQUE_COORD, PLACE_NAME, CITY, COUNTRY, IMAGE "
            "FROM IMAGES LEFT JOIN LOCATIONS ON IMAGES.FK_LOCATIONS_UNIQUE_COORD = LOCATIONS.UNIQUE_COORD "
            "WHERE CLIENT_TYPE IN (SELECT CLIENT_TYPE FROM CLIENT_STATE WHERE ENABLED = 1) "
            "AND CLIENT_TYPE IN (%@)",[clientTypes componentsJoinedByString:@"','"]];

【讨论】:

  • 谢谢。 . .我在想这样的事情会做。 . . MartinR 还给了我一个链接,让我可以将其作为 SQL 参数列表。 . .这样做有什么害处吗?我想不出任何会导致我们所知的文明终结的事情。
  • 我看到了,但我认为componentsJoinedByString 更容易阅读。
  • 这种解决方案的缺点可能是它没有在准备好的语句中将参数绑定到占位符。如果你只有一个整数数组,那么就不会有问题。但是,如果任何字符串包含括号、引号或类似内容,那么您很容易受到 SQL 注入攻击……这:xkcd.com/327 是我对该问题的标准参考。
  • 我以后肯定会使用@MartinR 的技术(不是为了避免SQL 注入,而是为了正确处理非转义字符)。 .鉴于在这种情况下我有一个数字列表,我将简写它。
  • @MartinR 我非常同意,但假设只允许使用整数,那么捷径并不可怕。此外,数据库没有在 Web 服务器上运行,故意对您自己的设备进行恶意攻击是没有意义的。
猜你喜欢
  • 2012-01-13
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多