2015-06-14 5 views
7

Ich verwende SQLite in einer iOS-Anwendung und ich verwende FMDB als Wrapper. Das ist meine Datenbankschema:Abrufen komplexer Daten mit FMDB

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); 

Meine Modellobjekte:

@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 

Zum Beispiel habe ich alle Angebote wie diese in der Datenbank bin holen:

- (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] 

} 

Dies funktioniert, aber es braucht Zeit, weil ich viele SQL-Anfragen verwende, um alle Angebote und die entsprechenden Märkte abzurufen.

Kann ich viele SQL Anfragen vermeiden, alle Angebote mit den entsprechenden Märkten zu holen? Vielen Dank für Ihre Antworten

Antwort

5

Was kann ich vorschlagen, ist:

  • Verfeinern Sie Ihre SQL-Anweisung. Anstelle von 2 Schleifen können Sie einfach Ihre Aussage in "SELECT * FROM OffreMarket WHERE codeOffer IN (SELECT code FROM Offer)" ändern. Wenn Sie die Spalte "name" in der Tabelle "Offer" verwenden möchten, können Sie zwei Tabellen "codeOffer" und "Offer" miteinander verbinden. Die Faustregel hier ist, zu viele Schleifen zu vermeiden, aber versuchen, Ihre SQL-Anweisung zu kombinieren oder zu verfeinern.

  • Index für Spalte "code" in Tabelle "Offer" erstellen. Es wird Ihre Suche viel beschleunigen. Zum Beispiel musste ich einmal in einem meiner Projekte an einer SQL-Tabelle mit 36K-Datensätzen arbeiten. Mit einem einfachen Index für die Primärschlüsselspalte konnte ich die Suchzeit auf dieser Tabelle um 10 Sekunden reduzieren.

+0

Danke für Ihre Antwort. Können Sie bitte ein Codebeispiel geben, wie Sie eine SQL-Anfrage ausführen, um die Angebote und die entsprechenden Märkte für jedes Angebot abzurufen? (Ich verstehe nicht, wie man das gleiche Objekt analysiert, um die Angebote und die Märkte zu haben. – samir

4

In diesem Fall können Sie die Ergebnisse mit nur einer Anfrage bekommen:

select * from Offer 
left outer join OffreMarket OM on (OM.codeOffer = Offer.code) 
2

Wenn Sie FMDB als Wrapper verwenden als hier ist die Antwort:

@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; 

oben Versuchen Code..it erhalten Sie alle Daten in kürzester Zeit. FMDB ist eine gute Wahl für den Datenbankbetrieb.

+0

Aber ich möchte die Angebote (Angebot) Objekte und alle entsprechenden Beziehungen (ich meine für jedes Angebot objet die Liste von OffreMarket) und die Das Gleiche gilt für alle OffreMarket-Objekte.Ihr Code holt nur die Angebotsobjekte und nicht die entsprechenden Beziehungen. Clear? – samir

+0

Siehe meine aktualisierte Antwort. Inner Join-Abfrage wird Ihnen helfen, Ihre Frage zu finden. –

+0

Und wie Sie das ResultSet analysieren? – samir