Вставить несколько таблиц в одной базе данных в sqlite - PullRequest
0 голосов
/ 09 июня 2011

Создавая приложение для Iphone, я использовал INSERT QUERY для разных баз данных.Но когда я попытался вставить данные в одну и ту же базу данных, я получил ошибку подтверждения.Я читаю два разных XML-URL и пытаюсь создать, а затем вставить данные в таблицу так, как они читаются при создании БД.У кого-нибудь есть идеи, почему это показывает мне ошибку?У меня есть следующий код, который вставляет в БД с использованием SQLITE:

  -(void) insertProductTable:(NSMutableArray *)Dict{
[Dict retain];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dbPath = [documentsDirectory stringByAppendingPathComponent:@"product.sql"];
NSInteger i;

if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {

    const char * insert_product_sql = "INSERT OR REPLACE INTO test(ID,KEY ) VALUES (?,?)" ;
    if(sqlite3_prepare_v2(database, insert_product_sql, -1, &product_statement, nil) != SQLITE_OK){
        NSAssert1(0, @"Error: failed to prepare insert_product_sql: '%s'.", sqlite3_errmsg(database));
    }

    for (i = 0; i < [self.array count]; i++) {
     sqlite3_bind_text(product_statement, 1, [[Dict valueForKey:@"ID"] UTF8String] ,-1, SQLITE_TRANSIENT);
     sqlite3_bind_text(product_statement, 2, [[Dict valueForKey:@"KEY"] UTF8String] ,-1, SQLITE_TRANSIENT);
    }

    if (sqlite3_step(product_statement) != SQLITE_DONE) {
        NSAssert(0,@"Error updating table");
    }

    [Dict release]; Dict = 0;
    sqlite3_finalize(product_statement);
    sqlite3_close(database);

}
}

У меня есть следующий метод, который выполняет другую функцию вставки, но другую таблицу, но на этом этапе он не позволяет мне вставить бросая меня Assertion Failure,Оба метода вызываются разными классами.

    -(void) insertTable:(NSMutableArray *)Dict{
[Dict retain];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dbPath = [documentsDirectory stringByAppendingPathComponent:@"product.sql"];
NSInteger i;

if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {

    const char * insert_sql = "INSERT OR REPLACE INTO test1(Term,Value ) VALUES (?,?)" ;
    if(sqlite3_prepare_v2(database, insert_sql, -1, &product_statement, nil) != SQLITE_OK){
        NSAssert1(0, @"Error: failed to prepare insert_sql: '%s'.", sqlite3_errmsg(database));
    }

    for (i = 0; i < [self.arayList count]; i++) {
     sqlite3_bind_text(product_statement, 1, [[Dict valueForKey:@"TERM"] UTF8String] ,-1, SQLITE_TRANSIENT);
     sqlite3_bind_text(product_statement, 2, [[Dict valueForKey:@"VALUE"] UTF8String] ,-1, SQLITE_TRANSIENT);
    }

    if (sqlite3_step(product_statement) != SQLITE_DONE) {
        NSAssert(0,@"Error updating table");
    }

    [Dict release]; Dict = 0;

    sqlite3_finalize(product_statement);
    sqlite3_close(database);

}
}

1 Ответ

1 голос
/ 09 июня 2011

@ lifemoveson

Я использовал ваш код для отладки и обнаружил, что функция

sqlite3_prepare_v2(database, insert_product_sql, -1, &product_statement, nil)

каждый раз возвращает 1 и соответствует вашей отсутствующей базе данных в нужном месте.

Я предлагаю вам создать такую ​​функцию, как эта

-(void)checkAndCreateDatabase{
    databaseName = @"MasterDB.sqlite";
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [documentPaths objectAtIndex:0];
    databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
    NSLog(@"database path %@",databasePath);
    BOOL success;

    // Create a FileManager object, we will use this to check the status
    // of the database and to copy it over if required
    NSFileManager *fileManager = [NSFileManager defaultManager];

    // Check if the database has already been created in the users filesystem
    success = [fileManager fileExistsAtPath:databasePath];

    // If the database already exists then return without doing anything
    if(success) return;

    // If not then proceed to copy the database from the application to the users filesystem

    // Get the path to the database in the application package
    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];

    // Copy the database from the package to the users filesystem
    [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
    //[fileManager release];

    // Now we can add new table

    sqlite3 *database;
    sqlite3_stmt *statement; 
    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
    {

        NSString *sqlQuery = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS tbl_Login (userId integer PRIMARY KEY,userName text,password text);"] ;
        const char *create_stmt = [sqlQuery UTF8String];
        sqlite3_prepare_v2(database, create_stmt, -1, &statement, NULL);

        if(sqlite3_step(statement)==SQLITE_DONE) 
        {
            NSLog(@"Table created");            
        }
        else 
        {
            NSLog(@"Table could not be created");
        }   
        // Release the compiled statement from memory
        sqlite3_finalize(statement);    
        sqlite3_close(database);
    }
}

, которая устанавливает переменную вашего класса databasePath и гарантирует, что перед выполнением любого запроса к базе данных база данных фактически присутствует вкаталог документов приложения.Вы можете вызвать эту функцию в приложении делегат

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//Other code 
[self checkAndCreateDatabase];

}

Когда вы делаете какой-либо вызов базы данных, используйте этот

const char *dbpath = [databasePath UTF8String];
    if (sqlite3_open(dbpath , &database) == SQLITE_OK) {
//Code to perform insert operations
 }

, я бы предложил вам написать отдельный класс для всех операций с базой данных, которые вывыполнить и вместо этого вызвать функцию класса для достижения желаемой функциональности.Это избавит вас от переписывания кода.

Для этого вы можете использовать оболочку FMDB, которую вы можете найти здесь

Надеюсь, это поможет: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...