iOS 6:尝试从不同路径的2个数据库中进行选择

时间:2013-03-22 13:20:54

标签: ios sqlite

我有两个数据库。

  1. ch_coins.db是[NSBundle mainBundle]中tableview的只读数据。
  2. 文档中的User_data.sqlite
  3. 我尝试将两个数据库中的select组合并将数据填充到object。我的方法是这样的:

    -(NSMutableArray*)returnSubCountries
    {
    NSString *path = [[[NSBundle mainBundle] resourcePath]
                      stringByAppendingPathComponent:databaseName];
    
    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [paths objectAtIndex:0];
    NSString *userDB = [documentsDir stringByAppendingPathComponent:user_data];
    
    
    NSMutableArray *subCountiresArr=[[NSMutableArray alloc]init];
    
    if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
    {
    
        /*const char *sqlSubCountries="SELECT subCountryID,subCountryName,subCountryComment,image,priority,hasRegions,navigationKey\
        FROM subCountries\
        ORDER BY priority ASC";*/
        const char *sqlSubCountries="SELECT subCountryID,subCountryName,subCountryComment,image,priority,hasRegions,navigationKey,usdb.quantity\
        attach database 'userDB' as usdb\
        INNER JOIN usdb on subCountries.subCountryID=usdb.refID\
        FROM subCountries\
        ORDER BY priority ASC";
        sqlite3_stmt *statement;
        int sqlResult = sqlite3_prepare_v2(database, sqlSubCountries, -1, &statement, NULL);
        if ( sqlResult== SQLITE_OK)
        {
            while (sqlite3_step(statement) == SQLITE_ROW)
            {
                SubCountry *sbCountryObj=[[SubCountry alloc]init];
                sbCountryObj.subCountryID=sqlite3_column_int(statement, 0);
                char *subCountryName=(char *)sqlite3_column_text(statement, 1);
                char *subCountryComment=(char *)sqlite3_column_text(statement, 2);
                char *image=(char *)sqlite3_column_text(statement, 3);
                sbCountryObj.priority=sqlite3_column_int(statement, 4);
                sbCountryObj.hasRegions=(sqlite3_column_int(statement, 5)==1);
                sbCountryObj.navigationKey=sqlite3_column_int(statement, 6);
                sbCountryObj.quantity=sqlite3_column_int(statement, 7);
                sbCountryObj.subCountryName=(subCountryName)?[NSString stringWithUTF8String:subCountryName]: @"";
                sbCountryObj.subCountryComment=(subCountryComment)?[NSString stringWithUTF8String:subCountryComment]: @"";
                sbCountryObj.image=(image)?[NSString stringWithUTF8String:image]: @"";
                [subCountiresArr addObject:sbCountryObj];
            }
            sqlite3_finalize(statement);
            sqlite3_close(database);
        }
    }
    else
    {
        //[self dbConnectionError];
    }
    return subCountiresArr;
    }
    

    我一定是做错了。任何帮助深表感谢。感谢名单。

    编辑:

    -(NSMutableArray*)returnSubCountries
    {
    NSString *path = [[[NSBundle mainBundle] resourcePath]
                      stringByAppendingPathComponent:databaseName];
    
    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [paths objectAtIndex:0];
    NSString *userDB = [documentsDir stringByAppendingPathComponent:user_data];
    
    
    NSMutableArray *subCountiresArr=[[NSMutableArray alloc]init];
    
    if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
    {
    
        /*const char *sqlSubCountries="SELECT subCountryID,subCountryName,subCountryComment,image,priority,hasRegions,navigationKey\
        FROM subCountries\
        ORDER BY priority ASC";*/
        NSString *userDBName = [NSString stringWithFormat:@"attach database '%@' as usdb", userDB];
        const char *sqlAttachedDatabase = [userDBName UTF8String];
    
        const char *sqlSubCountries="SELECT subCountryID,subCountryName,subCountryComment,image,priority,hasRegions,navigationKey,usdb.quantity\
        sqlAttachedDatabase userDB as usdb\
        INNER JOIN usdb on subCountries.subCountryID=usdb.refID\
        FROM subCountries\
        ORDER BY priority ASC";
        sqlite3_stmt *statement;
        int sqlResult = sqlite3_prepare_v2(database, sqlSubCountries, -1, &statement, NULL);
        if ( sqlResult== SQLITE_OK)
        {
            while (sqlite3_step(statement) == SQLITE_ROW)
            {
                SubCountry *sbCountryObj=[[SubCountry alloc]init];
                sbCountryObj.subCountryID=sqlite3_column_int(statement, 0);
                char *subCountryName=(char *)sqlite3_column_text(statement, 1);
                char *subCountryComment=(char *)sqlite3_column_text(statement, 2);
                char *image=(char *)sqlite3_column_text(statement, 3);
                sbCountryObj.priority=sqlite3_column_int(statement, 4);
                sbCountryObj.hasRegions=(sqlite3_column_int(statement, 5)==1);
                sbCountryObj.navigationKey=sqlite3_column_int(statement, 6);
                sbCountryObj.quantity=sqlite3_column_int(statement, 7);
                sbCountryObj.subCountryName=(subCountryName)?[NSString stringWithUTF8String:subCountryName]: @"";
                sbCountryObj.subCountryComment=(subCountryComment)?[NSString stringWithUTF8String:subCountryComment]: @"";
                sbCountryObj.image=(image)?[NSString stringWithUTF8String:image]: @"";
                [subCountiresArr addObject:sbCountryObj];
            }
            sqlite3_finalize(statement);
            sqlite3_close(database);
        }
        else
        {
            NSLog(@"%s: prepare failed: %s", __FUNCTION__, sqlite3_errmsg(database));
        }
    }
    else
    {
        //[self dbConnectionError];
    }
    return subCountiresArr;
    }
    

2 个答案:

答案 0 :(得分:1)

您应该执行以下操作:

  1. 运行SQL“attach database”full db path'as usdb“,其中”full db path“是数据库文件的完整路径
  2. 准备并执行SELECT语句(从中删除“attach database ...”)
  3. 在不需要时分离数据库“分离数据库'完整数据库路径'”

答案 1 :(得分:1)

您在SQL中将数据库路径指定为userDB,但这不是数据库文件的名称。也就是说,其中包含完整路径名的变量的名称,但您可能实际上必须使用该文件名构建SQL。例如:

NSString *sql = [NSString stringWithFormat:@"attach database '%@' as usdb", userDB];
const char *sqlAttachedDatabase = [sql UTF8String];

执行。然后,作为单独的语句,您可以执行使用usdb别名的SELECT SQL。当你完成后,分离数据库。

此外,我注意到您正在检查结果是否为SQLITE_OK(这是好的)。但是,如果不是,那么您没有显示任何诊断信息。例如,您的SQL错误,但您没有显示有意义的错误消息。因此,如果sqlite3_prepare_v2未能返回SQLITE_OK,您应该:

NSLog(@"%s: prepare failed: %s", __FUNCTION__, sqlite3_errmsg(database));

如果你在遇到错误时这样做,你就能弄明白什么是错的。没有它,你就会失明。


一个工作示例,我的“作者”数据库位于捆绑包中,而我的“book”数据库位于Documents中:

int rc;

NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *bookFilename = [docsPath stringByAppendingPathComponent:@"book.sqlite"];

NSString *authorFilename = [[NSBundle mainBundle] pathForResource:@"author" ofType:@"sqlite"];

sqlite3 *database;

if ((rc = sqlite3_open([authorFilename UTF8String], &database)) != SQLITE_OK)
{
    NSLog(@"%s: open failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);
    return;
}

NSString *sql = [NSString stringWithFormat:@"attach database '%@' as userdb;", bookFilename];

if ((rc = sqlite3_exec(database, [sql UTF8String], NULL, NULL, NULL)) != SQLITE_OK)
    NSLog(@"%s: attach failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);

sqlite3_stmt *statement;

sql = @"select book.*, author.* from userdb.book inner join author on author_id = book_author_id;";

if ((rc = sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL)) != SQLITE_OK)
    NSLog(@"%s: prepare failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);

while ((rc = sqlite3_step(statement)) == SQLITE_ROW)
{
    // do whatever you want row by row
    NSLog(@"Row");
}

if (rc != SQLITE_DONE)
    NSLog(@"%s: step failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);

sqlite3_finalize(statement);

sql = @"detach database userdb;";

if ((rc = sqlite3_exec(database, [sql UTF8String], NULL, NULL, NULL)) != SQLITE_OK)
    NSLog(@"%s: detach failed: %s (%d)", __FUNCTION__, sqlite3_errmsg(database), rc);

sqlite3_close(database);