передовая практика sqlite iphone для чтения данных

Я пытаюсь сделать приложение, которое читает из базы данных SQLite3. Я планирую предварительно загружать данные во время разработки, поэтому приложение не нуждается в изменении чего-либо в базе данных, только чтение из него, создание запросов и т. Д.

Какова наилучшая практика исключительно для чтения данных? Должен ли я открывать базу данных, читать данные и закрывать их с каждым запросом? Приложение будет делать множество небольших запросов и несколько крупных. Лучше ли открывать базу данных в течение всего времени приложения или открывать / закрывать ее с каждой выборкой?

Чтение:

1. Для запросов важно повторно использовать скомпилированные операторы.
2. Убедитесь, что вы используете параметры, чтобы вы могли повторно использовать эти скомпилированные запросы

Когда вы вызываете sqlite3_prepare_v2, он компилирует оператор и возвращает ссылку на инструкцию. Найдите способ сохранить это и повторно использовать его. См. Код для инструкции *. Вы проходите и заявляете в процессе подготовки.

Также обратите внимание на использование? для параметров. Если вы собираетесь повторно использовать инструкцию, важно вызвать sqlite3_reset () снова в инструкции, откорректировать входы из программы (параметры) и выполнить ее снова.

sqlite3_stmt *statement; NSString *querySQL = @"update contacts set name=?,address=?,phone=? where id=?"; NSLog(@"query: %@", querySQL); const char *query_stmt = [querySQL UTF8String]; // preparing a query compiles the query so it can be re-used. // find a way to save off the *statement so you can re-use it. sqlite3_prepare_v2(_contactDb, query_stmt, -1, &statement, NULL); // use sqlite3_bind_xxx functions to bind in order values to the params sqlite3_bind_text(statement, 1, [[contact name] UTF8String], -1, SQLITE_STATIC); sqlite3_bind_text(statement, 2, [[contact address] UTF8String], -1, SQLITE_STATIC); sqlite3_bind_text(statement, 3, [[contact phone] UTF8String], -1, SQLITE_STATIC); sqlite3_bind_int64(statement, 4, [[contact id] longLongValue]); 

Всегда проверяйте коды возврата! и регистрировать или обрабатывать ошибки.

  rc = sqlite3_step(stmt); switch (rc) { case SQLITE_ROW: // ... break; case SQLITE_OK: case SQLITE_DONE: break; default: // .... } return NO; } 

если вы получите сообщение об ошибке, войдите в систему или получите сообщение eror, чтобы предоставить дополнительную информацию:

 - (NSString*)errorMessage { return [NSString stringWithCString:sqlite3_errmsg(_sqlite3) encoding:NSUTF8StringEncoding]; } 

Используйте sqlite_open_v2 с флагом SQLITE_OPEN_READONLY . Например, я использую следующий метод для открытия базы данных только для чтения.

  // Open for reading only. - (int) openDatabaseAtPath:(NSString *) path { if (database != nil) { sqlite3_close(self.database); [self setDatabase:nil]; } int errorCode = SQLITE_OK; errorCode = sqlite3_open_v2([path UTF8String], &database, SQLITE_OPEN_READONLY, NULL); return errorCode; } 

Если вы не скопируете базу данных в каталог «Документы», вы работаете с БД из ресурса dir и этот только для чтения.

Когда вы открываете базу данных, используя sqlite_open_v2 и флаг SQLITE_OPEN_READONLY , SQLite открывает сам файл в режиме только для чтения, поэтому даже если ваше приложение из-за ошибки повреждает память, принадлежащую SQLite, база данных останется нетронутой.

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

По вашему вопросу вы хотите читать данные из базы данных. Итак, ответьте на ваши вопросы.

  1. Нет необходимости открывать db каждый раз, когда вы запускаете запрос. Только один раз. Лучше, если вы создадите одноэлементный класс и откроете db в нем в первый раз, когда он начнется.
  2. Используйте следующий метод кода, который будет работать для всех выбранных запросов, которые имеют условный выбор, группировать по и т. Д.
  3. I) он принимает имена столбца Output / result в качестве входного массива ii) TableName iii) где условие iv) предложение OrderBy v) group by clause

 - (NSMutableArray *)runSelecteQueryForColumns: (NSArray *)p_columns ontableName: (NSString *)p_tableName withWhereClause: (NSString *)p_whereClause withOrderByClause: (NSString *)p_orederByCalause withGroupByClause: (NSString *)p_groupByClause { NSMutableArray *l_resultArray = [[NSMutableArray alloc] init]; if(!self.m_database) { if(![self openDatabase]) { sqlite3_close(self.m_database); //NSLog(@"error in select : DB creating : %@",p_whereClause); return nil; } } NSMutableString *l_simpleQuery =[[NSMutableString alloc] initWithString:@"Select"] ; if(p_columns) { for(int l_row = 0 ; l_row < [p_columns count] ; l_row++) { if(l_row != [p_columns count]-1) { [l_simpleQuery appendString:[NSString stringWithFormat:@" %@,", [p_columns objectAtIndex:l_row]]]; } else { [l_simpleQuery appendString:[NSString stringWithFormat:@" %@", [p_columns objectAtIndex:l_row]]]; } } } else { [l_simpleQuery appendString:@" *"]; } [l_simpleQuery appendString:[NSString stringWithFormat:@" From %@",p_tableName]]; if(p_whereClause) { [l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_whereClause]]; } if(p_groupByCaluase) { [l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_groupByCaluase]]; } if(p_orederByCalause) { [l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_orederByCalause]]; } //NSLog(@"Select Query: - %@",l_simpleQuery); const char *l_query_stmt = [l_simpleQuery UTF8String]; sqlite3_stmt *l_statement = nil; int i = sqlite3_prepare_v2(self.m_database, l_query_stmt, -1, &l_statement, NULL); if (i == SQLITE_OK) { while(sqlite3_step(l_statement) == SQLITE_ROW) { [l_resultArray addObject:[self createDictionary:l_statement]]; } sqlite3_finalize(l_statement); } else { sqlite3_finalize(l_statement); //sqlite3_close(l_database); DDLogError(@"%@ - error in SQL :%@",THIS_FILE,l_simpleQuery); return nil; } //NSLog(@"RESULT %@",l_resultArray); return l_resultArray; }