Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在iphonesdk中实现动态查询_Iphone_Objective C_Ios - Fatal编程技术网

如何在iphonesdk中实现动态查询

如何在iphonesdk中实现动态查询,iphone,objective-c,ios,Iphone,Objective C,Ios,我想实现单个查询和动态查询。 有4个表,我使用GROUPBY子句过滤这些表。 但是现在我想组合这四个表并进行一个动态查询。 选择值时,t将如下所示: 例如: 步骤:1: entity1查询将是: Select * from TableName where entity1 = 'S' 步骤:2 实体2查询将是: Select * from TableName where entity1 = 'S' AND entity 2 = '100S' Select * from TableName w

我想实现单个查询和动态查询。 有4个表,我使用GROUPBY子句过滤这些表。 但是现在我想组合这四个表并进行一个动态查询。 选择值时,t将如下所示: 例如:

步骤:1:

entity1查询将是:

Select * from TableName where entity1 = 'S'
步骤:2

实体2查询将是:

Select * from TableName where entity1 = 'S' AND entity 2 = '100S' 
Select * from TableName where entity1 = 'S' AND entity 2 = '100S' AND entity3 = 'Fly'
步骤:3

实体3查询将是:

Select * from TableName where entity1 = 'S' AND entity 2 = '100S' 
Select * from TableName where entity1 = 'S' AND entity 2 = '100S' AND entity3 = 'Fly'
您可以尝试使用NSString的“stringWithFormat”方法,例如

NSString *strQuery = [NSString stringWithFormat:@"Select * from TableName where entity1 = '%@' AND entity 2 = '%@'",@"S",@"100S"];
希望对你有帮助


干杯

对于静态值,您可以尝试

NSString *strQuery =@"Select * from TableName where entity1 = 'S' AND entity 2 = '100S'";
对于动态值,您可以尝试

NSString *strQuery = [NSString stringWithFormat:@"Select * from TableName where entity1 = '%@' AND entity 2 = '%@'",entity1_obj,entity2_obj];
有几点想法:

  • 最好列名中没有空格。如果有空格,则需要将列名加引号,例如

    Select * from TableName where entity1 = 'S' AND 'entity 2' = '100S'
    
    最好完全绕过这个问题,确保列名中没有空格,例如
    entity2
    而不是
    entity2

  • 与使用
    stringWithFormat
    构建SQL相比,在SQL中使用
    占位符然后使用设置值更安全。这样,如果变量中的任何字符可能会弄乱手动创建的SQL语句(例如,该字段有一个单引号字符,
    ),则它将绕过该问题。因此,您可能有:

    sqlite3 *database;
    if (sqlite3_open([databasePath UTF8String], &database) != SQLITE_OK)
        NSLog(@"%s open error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
    
    NSString *sql = @"Select * from TableName where entity1 = ? AND entity2 = ?";
    NSString *entity1 = @"S";
    NSString *entity2 = @"100S";
    
    sqlite3_stmt *statement;
    
    if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL) != SQLITE_OK)
        NSLog(@"%s prepare SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
    
    if (sqlite3_bind_text(statement, 1, [entity1 UTF8String], -1, NULL) != SQLITE_OK)
        NSLog(@"%s bind entity 1 error '%s'", __FUNCTION__, sqlite3_errmsg(database));
    
    if (sqlite3_bind_text(statement, 2, [entity2 UTF8String], -1, NULL) != SQLITE_OK)
        NSLog(@"%s bind entity 2 error '%s'", __FUNCTION__, sqlite3_errmsg(database));
    
    int rc;
    
    while ((rc = sqlite3_step(statement)) == SQLITE_ROW)
    {
        // do whatever you want with the results
    
        const unsigned char *entity1 = sqlite3_column_text(statement, 0);
        const unsigned char *entity2 = sqlite3_column_text(statement, 1);
        const unsigned char *entity3 = sqlite3_column_text(statement, 2);
    
        NSLog(@"%s %s %s", entity1, entity2, entity3);
    }
    
    if (rc != SQLITE_DONE)
        NSLog(@"%s step SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
    
    sqlite3_finalize(statement);
    sqlite3_close(database);
    
    诚然,这种使用sqlite\u bind\u text的方式有点麻烦,但更健壮。如果不能完全确定要查找的字段是否具有单引号字符,则使用此约定非常重要。如果您是根据用户提供的一些搜索条件构建SQL,这一点非常重要(例如,查找“Joe's Bar and Grill”,如果您不使用
    sqlite3\u bind\u text
    或围绕此问题编写代码,“Joe's”中的撇号可能会让您有点心痛)。虽然这对于一个应用程序来说并不像一个网站那么重要,但你只是不希望你的应用程序容易受到攻击

  • 如果您使用一个非常好的sqlite小Objective-C包装器,上面的
    sqlite\u bind\u text
    语法将大大简化:

    FMDatabase *database = [FMDatabase databaseWithPath:databasePath];
    NSAssert(database, @"unable to open database");
    
    if (![database open])
        NSLog(@"%@", [self.database lastErrorMessage]);
    
    FMResultSet *rs = [database executeQuery:@"Select * from TableName where entity1 = ? AND entity2 = ?", @"S", @"100S"];
    NSAssert(rs, [self.database lastErrorMessage]);
    
    while ([rs next])
    {
        NSLog(@"%@ %@ %@", rs[0], rs[1], rs[2]);
    }
    
    [rs close];
    [database close];
    
    这可以享受到
    sqlite\u bind\u text
    的好处,而无需将您拖入
    sqlite
    函数调用的杂草中


  • 如果您想拥有一个可以使用可变数量的参数调用的函数,那么可以通过多种不同的方式来实现,动态构建SQL。我将在下面提供一个示例,并声明我真的不喜欢手动构建SQL,因为代码最终会遇到可读性问题。我宁愿用更清晰的东西来牺牲节俭的代码,但我从您的问题中推断,您想知道如何动态构建SQL,因此我将提供一个示例,并附带上述警告。我还要说有很多方法可以解决这个问题,这只是一个这样的例子

    无论如何,假设您想使用字典作为参数,指定哪些列具有哪些值,您可以按如下方式调用它。如果您只有实体1,您可以这样称呼它:

    [self selectTableWithDictionary:@{@"entity1":@"S"}];
    
    [self selectTableWithDictionary:@{@"entity1":@"S", @"entity2":@"100S"}];
    
    或者,如果您同时拥有实体1和实体2,您可以这样称呼它:

    [self selectTableWithDictionary:@{@"entity1":@"S"}];
    
    [self selectTableWithDictionary:@{@"entity1":@"S", @"entity2":@"100S"}];
    
    然后解析此字典、手动构建SQL并绑定各个列的方法可能如下所示:

    - (void)selectWithDictionary:(NSDictionary *)dictionary
    {
        NSArray *fieldNames = [dictionary allKeys];
        NSArray *values = [dictionary allValues];
    
        // build the sql
    
        NSMutableString *sql = [NSMutableString stringWithString:@"Select * from TableName"];
        if ([fieldNames count]){
            [sql appendString:@" where "];
            [sql appendString:[fieldNames componentsJoinedByString:@" = ? AND "]];
            [sql appendString:@" = ?"];
        }
    
        sqlite3_stmt *statement;
    
        // prepare the sql
    
        if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL) != SQLITE_OK)
            NSLog(@"%s prepare SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
    
        // bind the values
    
        for (NSInteger i = 0; i < [fieldNames count]; i++)
            if (sqlite3_bind_text(statement, i+1, [values[i] UTF8String], -1, NULL) != SQLITE_OK)
                NSLog(@"%s bind column # %d error '%s'", __FUNCTION__, i+1, sqlite3_errmsg(database));
    
        int rc;
    
        // iterate through the results
    
        while ((rc = sqlite3_step(statement)) == SQLITE_ROW)
        {
            const unsigned char *entity1 = sqlite3_column_text(statement, 0);
            const unsigned char *entity2 = sqlite3_column_text(statement, 1);
            const unsigned char *entity3 = sqlite3_column_text(statement, 2);
    
            NSLog(@"%s %s %s", entity1, entity2, entity3);
        }
    
        if (rc != SQLITE_DONE)
            NSLog(@"%s step SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
    
        sqlite3_finalize(statement);
    }
    
    - (void)selectTableWithDictionary:(NSDictionary *)dictionary
    {
        NSArray *fieldNames = [dictionary allKeys];
        NSArray *values = [dictionary allValues];
    
        // build the sql
    
        NSMutableString *sql = [NSMutableString stringWithString:@"Select * from TableName"];
        if ([fieldNames count]){
            [sql appendString:@" where "];
            [sql appendString:[fieldNames componentsJoinedByString:@" = ? AND "]];
            [sql appendString:@" = ?"];
        }
    
        // execute the sql
    
        FMResultSet *rs = [self.database executeQuery:sql
                                 withArgumentsInArray:values];
        NSAssert(rs, [self.database lastErrorMessage]);
    
        // iterate through the results
    
        while ([rs next])
        {
            NSLog(@"%@ %@ %@", rs[0], rs[1], rs[2]);
        }
    
        [rs close];
    }
    

    entity1、2和3是什么意思?当选择表中的值时,我必须追加字符串,然后执行动态查询。你能告诉我你的邮箱号码吗