Fetching complex data using FMDB

1.5k views Asked by At

I am using SQLite in an iOS application and I am using FMDB as a wrapper. This is my database schema :

CREATE TABLE Offer (code TEXT PRIMARY KEY NOT NULL, name TEXT);

CREATE TABLE OffreMarket (codeOffer TEXT NOT NULL,
codeMarket TEXT NOT NULL,
FOREIGN KEY(codeOffer) REFERENCES Offer(code),
FOREIGN KEY(codeMarket) REFERENCES Market(code));

CREATE TABLE Market (code TEXT PRIMARY KEY NOT NULL, name TEXT);

My model objects :

@interface Offer : NSObject
@property (nonatomic,copy) NSString *code;
@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSArray *markets;
@end

@interface OffreMarket : NSObject
@property (nonatomic,copy) NSString *codeOffer;
@property (nonatomic,copy) NSString *codeMarket;
@end

@interface Market : NSObject
@property (nonatomic,copy) NSString *code;
@property (nonatomic,copy) NSString *name;
@end

For example I am fetching all the offers in the database like this :

- (NSArray *)offers {
// Open database

NSMutableArray *offers = [NSMutableArray new];

FMResultSet *resultSet = [database executeQuery:@"SELECT * FROM Offer"];
while ([resultSet next]){

   Offer *offer = [Offer new];
   offer.code = [resultSet stringForKey:@"code"];
   offer.name = [resultSet stringForKey:@"name"];

   // Get the markets for each offer
   FMResultSet *marketResultSet = [database executeQuery:@"SELECT * FROM  OffreMarket WHERE codeOffer = ?",offer.code];

   NSMutableArray *offers = [NSMutableArray new];
   while ([marketResultSet next]) {
      OffreMarket *offerMarket = [OffreMarket new];
      ....
     [offers addObject:offerMarket];
   }

  market.offers = [offers copy];
}

return [offers copy]

}

This is working but it takes time because I am using many SQL requests to fetch all the Offers and the corresponding Markets.

Can i avoid many SQL requests to fetch all the Offers with the corresponding markets? Thanks for your answers

3

There are 3 answers

1
Daniel Le On BEST ANSWER

What I can suggest is:

  • Refine your SQL statement. Instead of 2 loops, you can simply change your statement into "SELECT * FROM OffreMarket WHERE codeOffer IN (SELECT code FROM Offer)". If you want to use column "name" in table "Offer", you can join two tables "codeOffer" and "Offer". The rule of thumb here is to avoid too many loops but try to combine or refine your SQL statement.

  • Create index for column "code" in table "Offer". It will speed up your searching a lot. For example, once in one of my project, I had to work on a SQL table with 36K records. With a simple index set to the primary key column, I managed to reduce the searching time on that table by 10 seconds.

0
dan b On

In this case you can get the results with just one query:

select * from Offer
left outer join OffreMarket OM on (OM.codeOffer = Offer.code)
8
Code Hunterr On

If you are using FMDB as a wrapper than here is your answer:

@try {

    // Select Contact Details From Modules
    NSString *selectSQL = [NSString stringWithFormat:
                           @"SELECT * FROM %@ INNER JOIN %@ ON %@.%@=%@.%@ ;",
                           OffreMarket,
                           Offer,
                           OffreMarket
                           code
                           Offer
                           code];

    //NSLog*(@"Get All Offers select SQL: %@", selectSQL);
    FMResultSet *resultSet = [db executeQuery:selectSQL];
    NSMutableArray *marketOffers = [[NSMutableArray alloc]init];

    while ([resultSet next]) {

        // Create Offers Details Modal
        Offer *offer = [[Offer alloc] init];

         offer.code = [resultSet stringForKey:@"code"];
         offer.name = [resultSet stringForKey:@"name"];

        [marketOffers addObject: offer];
    }
    return (NSArray *)infos;
}
@catch (NSException *exception) {

    //NSLog*(@"%@ : %@",exception.name,exception.reason);
    return nil;
}
return nil;

Try above Code..it will get you all the data in minimum time. FMDB is nice choice for database operation.