将整数数组传递给sqlite以获取'IN'子句的最佳方法

时间:2013-10-30 12:35:17

标签: sql objective-c sqlite fmdb

我正在实现一个基于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查询。 。鉴于它们只是整数,这将是非常安全的。

1 个答案:

答案 0 :(得分: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:@"','"]];