sqlite iphone读取数据的最佳实践

时间:2011-09-25 23:17:51

标签: ios iphone sqlite

我正在尝试创建一个从SQLite3数据库读取的应用程序。我计划在开发期间预加载数据,因此应用程序不需要修改数据库中的任何内容,只需从中读取,进行查询等。

单独阅读数据的最佳做法是什么?我应该打开数据库,读取数据并关闭它,每次查询?该应用程序将进行许多小型查询和一些大型查询。在应用程序的持续时间内打开数据库是不是更好,或者每次获取都打开/关闭它?

5 个答案:

答案 0 :(得分:1)

<强>读:

<强> 1。对于查询,重用已编译的语句很重要 2.确保使用参数,以便可以重复使用这些已编译的查询

当你调用sqlite3_prepare_v2时,它会编译语句并为你提供对语句的引用。找到一种方法来保存它并重新使用它。有关*语句,请参阅下面的代码。你将&amp;陈述传递给准备。

另外,注意使用?用于参数。如果你要重用这个语句,重要的是在语句中再次调用sqlite3_reset(),重新绑定程序中的输入(参数)并再次执行它。

sqlite3_stmt    *statement;
NSString *querySQL = @"update contacts set name=?,address=?,phone=? where id=?";
NSLog(@"query: %@", querySQL);
const char *query_stmt = [querySQL UTF8String];

// preparing a query compiles the query so it can be re-used.
// find a way to save off the *statement so you can re-use it.
sqlite3_prepare_v2(_contactDb, query_stmt, -1, &statement, NULL);  

// use sqlite3_bind_xxx functions to bind in order values to the params   
sqlite3_bind_text(statement, 1, [[contact name] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [[contact address] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 3, [[contact phone] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_int64(statement, 4, [[contact id] longLongValue]);

请务必查看退货代码!并记录或处理错误。

    rc = sqlite3_step(stmt);
    switch (rc)
    {
        case SQLITE_ROW:
            // ...
            break;

        case SQLITE_OK:
        case SQLITE_DONE:
            break;

        default:
            // ....
            }

            return NO;
    }

如果您收到错误,请记录或收到错误消息以提供更多信息:

- (NSString*)errorMessage
{
    return [NSString stringWithCString:sqlite3_errmsg(_sqlite3) encoding:NSUTF8StringEncoding];    
}

答案 1 :(得分:0)

sqlite_open_v2SQLITE_OPEN_READONLY标志一起使用。例如,我使用以下方法打开数据库以进行只读。

  // Open for reading only.
- (int) openDatabaseAtPath:(NSString *) path
{
    if (database != nil)
    {
        sqlite3_close(self.database);
        [self setDatabase:nil];
    }

    int errorCode = SQLITE_OK;
    errorCode = sqlite3_open_v2([path UTF8String],
                                 &database,
                                 SQLITE_OPEN_READONLY,
                                 NULL);

    return errorCode;
}

答案 2 :(得分:0)

除非您将数据库复制到Documents目录,否则您将使用资源目录中的数据库,并且该数据库是只读的。

答案 3 :(得分:0)

当您使用sqlite_open_v2SQLITE_OPEN_READONLY标志打开数据库时,SQLite以只读模式打开文件本身,因此即使您的应用程序由于某个错误而破坏了属于SQLite的内存,数据库将保持不变。

考虑到这一点,我会保持数据库处于打开状态,直到应用程序退出。 (如果收到内存不足通知并按需重新打开,您可能希望关闭它,但是为每个查询打开和关闭它都会很浪费。)

答案 4 :(得分:0)

根据您的问题,您想要从数据库中读取数据。以下是你问题的答案。

  1. 每次触发查询时都无需打开数据库。只有一次。如果你在启动时第一次创建单例类并打开db,那就更好了。
  2. 使用以下代码方法,该方法适用于具有条件选择,分组等的所有选择查询。
  3. I)它将输出/结果列名称作为输入数组ii)TableName iii)其中条件iv)OrderBy子句v)group By子句
  4. - (NSMutableArray *)runSelecteQueryForColumns: (NSArray *)p_columns ontableName: (NSString *)p_tableName withWhereClause: (NSString *)p_whereClause withOrderByClause: (NSString *)p_orederByCalause withGroupByClause: (NSString *)p_groupByClause
    {
    
    
        NSMutableArray *l_resultArray = [[NSMutableArray alloc] init];
    
        if(!self.m_database)
        {
            if(![self openDatabase])
            {
                sqlite3_close(self.m_database);
                //NSLog(@"error in select : DB creating : %@",p_whereClause);
                return nil;
    
            }
        }
    
        NSMutableString *l_simpleQuery =[[NSMutableString alloc] initWithString:@"Select"] ;
    
        if(p_columns)
        {
    
            for(int l_row = 0 ; l_row < [p_columns count] ; l_row++)
            {
                if(l_row != [p_columns count]-1)
                {
                    [l_simpleQuery appendString:[NSString stringWithFormat:@" %@,", [p_columns objectAtIndex:l_row]]];
                }
                else
                {
                    [l_simpleQuery appendString:[NSString stringWithFormat:@" %@", [p_columns objectAtIndex:l_row]]];
                }
            }
        }
        else
        {
            [l_simpleQuery appendString:@" *"];
        }
    
        [l_simpleQuery appendString:[NSString stringWithFormat:@" From %@",p_tableName]];
    
        if(p_whereClause)
        {
            [l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_whereClause]];
        }
        if(p_groupByCaluase)
        {
            [l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_groupByCaluase]];
        }
    
        if(p_orederByCalause)
        {
            [l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_orederByCalause]];
        }
    
    
        //NSLog(@"Select Query: - %@",l_simpleQuery);
    
        const char *l_query_stmt = [l_simpleQuery UTF8String];
    
        sqlite3_stmt *l_statement = nil;
    
        int i = sqlite3_prepare_v2(self.m_database,
                                   l_query_stmt, -1, &l_statement, NULL);
    
        if (i == SQLITE_OK)
        {
    
            while(sqlite3_step(l_statement) == SQLITE_ROW)
            {
    
                [l_resultArray addObject:[self createDictionary:l_statement]];
    
            }
    
            sqlite3_finalize(l_statement);
    
    
        }
        else
        {
            sqlite3_finalize(l_statement);
            //sqlite3_close(l_database);
            DDLogError(@"%@ - error in SQL :%@",THIS_FILE,l_simpleQuery);
            return nil;
        }
        //NSLog(@"RESULT %@",l_resultArray);
        return l_resultArray;
    
    }