1

2 つのデータベースがあります。

  1. ch_coins.db は [NSBundle mainBundle] 内の tableview の読み取り専用データです。
  2. ドキュメント内の User_data.sqlite

両方のデータベースから選択し、データをオブジェクトに入力しようとしています。私の方法はそのようなものです:

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

2 に答える 2

1

次のことを行う必要があります。

  1. SQL「attach database 'full db path' as usdb」を実行します。ここで、「full db path」はデータベース ファイルへのフル パスです。
  2. SELECT ステートメントを準備して実行します ("attach database ..." を削除します)。
  3. 不要な場合はデータベースを切り離す "detach database 'full db path'"
于 2013-03-22T13:58:10.287 に答える
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));

エラーが発生したときにこれを行うと、何が問題なのかを突き止めることができます。それがなければ、あなたは盲目的に飛んでいます。


私の "author" データベースがバンドルにあり、私の "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);
于 2013-03-22T14:20:42.680 に答える