2013-07-30 2 views
0

Я использовал sqlite DB для своего приложения, и мне нужно вызвать два одновременных запроса, но я даю ошибку как: Нагрузочный приложение из-за неперехваченного исключением «NSInternalInconsistencyException», причина: «ошибка подготовки заявление»iOS: ошибка базы данных Sqlite: завершение приложения из-за неотображенного исключения «NSInternalInconsistencyException», причина: «команда подготовки ошибки»

Я бегу таймер каждые 10 секунд для Выбор строк из БД и Вставка строк в БД после события кнопки ,

Мой фрагмент кода, как:

в viewWillAppear:

int result2 = sqlite3_open([dbPath UTF8String], &database); 
if (result2 != SQLITE_OK) { 
    NSLog(@"Failure in connecting to the database with result %d",result2); 
} 
else { 
    NSLog(@ "Succesfully opened connection to DB") ; 

} 

и viewWillDisappear:

int result = sqlite3_close(database); 
if (result != SQLITE_OK){ 
    NSLog(@"Failure in closing connection to database. Result %d",result); 
} 
else { 
    NSLog(@"Successfully closed DB connection") ; 
} 

Для Inserting rows:

NSString *queryInsert = [NSString stringWithFormat: @"insert into mail_snoozlist (msgBody,msgSubject, msgSender,msgTo,msgDate,snoozTime) values('%@','%@','%@','%@','%@','%@')",strBody,msgSub,msgFrom,msgTo,strMsgDate,stringFromDate]; 

    NSLog(@"queryInsert:%@",queryInsert); 

    const char *sql = [queryInsert UTF8String]; 

    if(sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) { 
     sqlite3_step(statement); 
     sqlite3_reset(statement); 

    } else { 

     NSAssert1(0,@"error preparing statement",sqlite3_errmsg(database)); 
     return; 
    } 

    sqlite3_finalize(statement); 

и Selecting rows:

NSString *querySQL2 = [NSString stringWithFormat: @"Select * from mail_snoozlist WHERE snoozTime = '%@'",_snoozTime]; 

    NSLog(@"querySql:%@",querySQL2); 

    if (sqlite3_prepare_v2(database, [querySQL2 UTF8String], -1, &statement, NULL) == SQLITE_OK) 
    { 

     while (sqlite3_step(statement) == SQLITE_ROW) 
     { 
      Message *obj = [[Message alloc] init]; 

      NSString *msgBody=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)]; 
      obj.msgBody= msgBody; 

      NSString *msgSub=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)]; 
      obj.msgSub= msgSub; 

      NSString *msgSender=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)]; 
      obj.msgFrom= msgSender; 

      NSString *msgTo=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)]; 
      obj.msgTo= msgTo; 

      NSString *msgDate=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)]; 
      obj.msgDate= msgDate; 

      [listOfItems addObject:obj]; 

      [self.tableView reloadData]; 
     } 

     sqlite3_reset(statement); 
     sqlite3_finalize(statement); 

Любой, пожалуйста, помогите мне решить эту проблему.

Спасибо!

ответ

0

Добавьте эти два метода и вызывать их в методе вставки перед вставкой и выбора,

- (void) createEditableCopyOfDatabaseIfNeeded 
{ 


    BOOL success; 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSError *error; 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"dbname.sqlite"]; 
    success = [fileManager fileExistsAtPath:writableDBPath]; 
    if (success) return; 
    //{ 

    NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"dbname.sqlite"]; 

    success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error]; 
    // } 
    if (!success) 
    { 
     NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]); 
    } 
} 


- (void)initializeDatabase 
{ 



NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"dbname.sqlite"]; 
sqlite3_open([path UTF8String], &database); 
} 
+0

для вызова этих строк // [self createEditableCopyOfDatabaseIfNeeded]; [self initializeDatabase]; – iAhmed

+1

Спасибо за ваш ответ. мне пришлось решать эту проблему путем изменения битов в запросе: 'NSString * queryInsert = [NSString stringWithFormat: @" вставить в mail_snoozlist (msgBody, msgSubject, msgSender, msgTo, msgDate, Snooztime) значения ('% S', '% s', '% s', '% s', '% s', '% s') ", [strBody UTF8String], [msgObj.msgSub UTF8String], [msgObj.msgFrom UTF8String], [msgObj.msgTo UTF8String], [strMsgDate UTF8String], [stringFromDate UTF8String]]; ' – Pankaj

1

Вы должны изменить свое NSAssert заявление включить сообщение об ошибке:

NSAssert1(0, @"error preparing statement: %s", sqlite3_errmsg(database)); 

После того, как вы сделаете это, вы должны получить полноценный ответ, который поможет вам диагностировать проблему.

Не смотря на сообщение sqlite3_errmsg, трудно диагностировать проблему. Это может быть так же просто, как опечатка в имени столбца или имени таблицы или сложнее, чем не найдена таблица, поскольку база данных не была найдена при ее создании, поэтому была создана пустая база данных (без этой таблицы). Трудно сказать, пока мы не увидим сообщение об ошибке.


Как и в сторону, вы не должны строить свой SQL с stringWithFormat, потому что вы открываете себя для атак SQL инъекций, а также будет иметь проблемы, если какой-либо из этих текстовых значений есть апостроф в них. Вы должны использовать ? заполнителей вместо форматтеров Printf стиле, а затем связать значения в этих колонках с sqlite3_bind_text вызовов:

NSString *queryInsert = @"insert into mail_snoozlist (msgBody,msgSubject, msgSender,msgTo,msgDate,snoozTime) values(?, ?, ?, ?, ?, ?)"; 

if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) != SQLITE_OK) { 
    NSAssert1(0,@"error preparing statement: %s",sqlite3_errmsg(database)); 
    return; 
} 

// for these 6 sqlite3_bind function calls, if any of these strings can be `nil`, then you'd 
// want to call sqlite3_bind_null if that's the case, rather than sqlite3_bind_text 

if (sqlite3_bind_text(statement, 1, [strBody UTF8String], -1, NULL) != SQLITE_OK) { 
    NSAssert1(0,@"error binding 1: %s",sqlite3_errmsg(database)); 
    sqlite3_finalize(statement); 
    return; 
} 

if (sqlite3_bind_text(statement, 2, [msgSub UTF8String], -1, NULL) != SQLITE_OK) { 
    NSAssert1(0,@"error binding 2: %s",sqlite3_errmsg(database)); 
    sqlite3_finalize(statement); 
    return; 
} 

if (sqlite3_bind_text(statement, 3, [msgFrom UTF8String], -1, NULL) != SQLITE_OK) { 
    NSAssert1(0,@"error binding 3: %s",sqlite3_errmsg(database)); 
    sqlite3_finalize(statement); 
    return; 
} 

if (sqlite3_bind_text(statement, 4, [msgTo UTF8String], -1, NULL) != SQLITE_OK) { 
    NSAssert1(0,@"error binding 4: %s",sqlite3_errmsg(database)); 
    sqlite3_finalize(statement); 
    return; 
} 

if (sqlite3_bind_text(statement, 5, [strMsgDate UTF8String], -1, NULL) != SQLITE_OK) { 
    NSAssert1(0,@"error binding 5: %s",sqlite3_errmsg(database)); 
    sqlite3_finalize(statement); 
    return; 
} 

if (sqlite3_bind_text(statement, 6, [stringFromDate UTF8String], -1, NULL) != SQLITE_OK) { 
    NSAssert1(0,@"error binding 6: %s",sqlite3_errmsg(database)); 
    sqlite3_finalize(statement); 
    return; 
} 

if (sqlite3_step(statement) != SQLITE_DONE) { 
    NSAssert1(0,@"error stepping: %s",sqlite3_errmsg(database)); 
} 

sqlite3_finalize(statement); 

Я иллюстрировать вопрос с insert утверждением, но то же самое должно быть сделано с select заявление , слишком.

+0

Спасибо за ваш ответ. мне пришлось решать эту проблему путем изменения битов в запросе: 'NSString * queryInsert = [NSString stringWithFormat: @" вставить в mail_snoozlist (msgBody, msgSubject, msgSender, msgTo, msgDate, Snooztime) значения ('% S', '% s', '% s', '% s', '% s', '% s') ", [strBody UTF8String], [msgObj.msgSub UTF8String], [msgObj.msgFrom UTF8String], [msgObj.msgTo UTF8String], [strMsgDate UTF8String], [stringFromDate UTF8String]]; ' – Pankaj

+0

@Pankaj Сначала вы должны добавить'% s' в свою строку 'NSAssert1', иначе вы никогда не увидите' sqlite3_errmsg', когда будете получать ошибки. Во-вторых, изменение '% @' на '% s' в вашем SQL только по совпадению работает, на самом деле не устраняет никаких проблем и делает код менее разборчивым. В-третьих, если ваше предлагаемое изменение пытается вставить 'strBody' или' msgSubject', в котором есть апостроф, и ваш код по-прежнему будет терпеть крах. Не используйте 'stringWithFormat' для построения SQL, а используйте' sqlite3_bind_text'. Кроме того, коварный пользователь может выполнить атаку SQL-инъекции, например. http://xkcd.com/327/ – Rob

+0

Я добавляю этот код, но теперь я получаю сообщение об ошибке: «Завершение приложения из-за неотображаемого исключения» NSInternalInconsistencyException », причина:« команда подготовки ошибки: библиотечная процедура вызвана из последовательности » , И я не получил никакого ** журнала привязки ошибок **. – Pankaj

Смежные вопросы

 Смежные вопросы