Sqlite iPhone读取数据的最佳实践



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

单独读取数据的最佳实践是什么?是否应该在每次查询时打开数据库、读取数据并关闭它?该应用程序将进行许多小查询和一些大查询。是让数据库在应用程序的持续时间内打开,还是在每次获取时打开/关闭它?

阅读:

1。对于查询,重用编译语句是很重要的。
2. 确保使用了参数,这样就可以重用那些编译好的查询

当您调用sqlite3_prepare_v2时,它将编译语句并返回对该语句的引用。想办法把它保存下来并重新使用。请参阅下面的*语句代码。将&语句传入prepare.

还要注意?为参数。如果您打算重用该语句,那么对该语句调用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];    
}

使用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;
}

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

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

考虑到这一点,我将保持数据库打开,直到应用程序退出。(如果您收到低内存通知并根据需要重新打开它,您可能希望关闭它,但是为每个查询打开和关闭它将是浪费的。)

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

  1. 每次启动查询时不需要打开db。一次就好。最好是创建单例类,并在它初始化时第一次在其中打开db。
  2. 使用以下代码方法,它将适用于所有有条件选择,分组等的选择查询
  3. I)将输出/结果列名作为输入数组ii) TableName iii) Where条件iv)OrderBy子句v)group By子句

- (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;
}

最新更新