Странная ошибка SQLite3: не удается найти столбец

#sql #objective-c #ios4 #sqlite

#sql #objective-c #ios4 #sqlite

Вопрос:

Я застрял на этой проблеме здесь. У меня есть приложение, которое считывает XML-файл. Эта информация правильно сохранена в NSMutableDictionary.

Следующее, что я хочу сделать, это добавить все элементы из этого NSMutableDictionary в базу данных с использованием SQLite3.

В делегате приложения я создаю базу данных с помощью:

 NSString *docsDir;
NSArray *dirPaths;

// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

docsDir = [dirPaths objectAtIndex:0];

// Build the path to the database file
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"incidents.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];

if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
    const char *dbpath = [databasePath UTF8String];

    if (sqlite3_open(dbpath, amp;contactDB) == SQLITE_OK)
    {
        char *errMsg;
        const char *sql_stmt = "CREATE TABLE IF NOT EXISTS INCIDENTS (ID INTEGER PRIMARY KEY, SERIAL TEXT, CI TEXT, FAMILY TEXT, DEVICEDESCRIPTION TEXT, LOCATION TEXT, SUBLOCATION TEXT, UPDOWN TEXT, PROBLEMDESCRIPTION TEXT, ADDINFO TEXT, PROBLEMLOCATION TEXT, PROBLEMCATEGORY TEXT, CONTFIRSTNAME TEXT, CONTLASTNAME TEXT, CONTSALUTATION TEXT, CONTPHONENUMBER TEXT, LOCALCALL TEXT, CICATEGORY TEXT, STATUS TEXT)";

        if (sqlite3_exec(contactDB, sql_stmt, NULL, NULL, amp;errMsg) != SQLITE_OK)
        {
            NSLog(@"Failed to create table");
        }

        sqlite3_close(contactDB);

    } else {
        NSLog(@"Failed to open/create database");
    }
}

[filemgr release];
  

В другом классе я использую код:

 NSString *insertSQL = [NSString stringWithFormat:@"INSERT INTO INCIDENTS (ID, SERIAL, CI, FAMILY, DEVICEDESCRIPTION, LOCATION, SUBLOCATION, UPDOWN, PROBLEMDESCRIPTION, ADDINFO, PROBLEMLOCATION, PROBLEMCATEGORY, CONTFIRSTNAME, CONTLASTNAME, CONTSALUTATION, CONTPHONENUMBER, LOCALCALL, CICATEGORY, STATUS) VALUES ("%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@", "%@")", [item objectForKey:@"ID"], [item objectForKey:@"Serial"], [item objectForKey:@"ConfigurationAlias"], [item objectForKey:@"Family"], [item objectForKey:@"DeviceDescription"], [item objectForKey:@"Location"], [item objectForKey:@"SubLocation"], [item objectForKey:@"UpDownIndicator"], [item objectForKey:@"ProblemDescription"], [item objectForKey:@"AdditionalInformation"], [item objectForKey:@"ProblemLocation"], [item objectForKey:@"ProblemCategory"], [item objectForKey:@"ContactPersonFirstName"], [item objectForKey:@"ContactPersonLastName"], [item objectForKey:@"ContactPersonSalutation"], [item objectForKey:@"ContactPersonPhoneNumber"], [item objectForKey:@"LocalCallNumber"], [item objectForKey:@"ConfigurationItemCategory"], [item objectForKey:@"Status"]];
const char *insert_stmt = [insertSQL UTF8String];
//NSLog(@"could not prepare statement: %sn", sqlite3_errmsg(contactDB));
sqlite3_prepare_v2(contactDB, insert_stmt, -1, amp;statement, NULL);
if(sqlite3_prepare_v2(contactDB, insert_stmt, -1, amp;statement, NULL) != SQLITE_DONE){
    NSLog(@"Error: Failed to prepare stmt with message '%s'", sqlite3_errmsg(contactDB));
}
if (sqlite3_step(statement) == SQLITE_DONE)
{
    NSLog(@"Succesfully added in DB");
} else {
    NSLog(@"Failed to add incident in DB");
}
sqlite3_finalize(statement);
sqlite3_close(contactDB);
  

Ошибка, которую я получаю, используя инструкцию sqlite3_errmsg, является:
2011-05-09 10:04:12.029 Fleet Manager[1053:207] Error: Failed to prepare stmt with message 'table INCIDENTS has no column named PROBLEMDESCRIPTION'

Есть идеи, что происходит?

РЕДАКТИРОВАТЬ: Это работает, когда я удаляю часть описания проблемы из добавления. Все еще проблема, поскольку она оставляет меня с пустым столбцом…

Ответ №1:

Из сообщения об ошибке ясно, что в таблице в вашей базе данных SQLite3 нет столбца PROBLEMDESCRIPTION. Я бы предположил, что в какой-то момент в вашем операторе create была допущена орфографическая ошибка, которая не была исправлена, потому что вы не воссоздаете таблицу, если она уже существует.

Чтобы убедиться в этом, откройте базу данных с помощью инструмента командной строки sqlite3 и запустите .schema INCIDENTS команду.


Кстати, очень плохая идея вставлять данные строки с помощью -stringWithFormat: Вы всегда должны использовать sqlite_bind*(), чтобы избежать проблем с экранированием зарезервированных символов.

Комментарии:

1. Вот и все. База данных не создается заново! Спасибо за помощь 🙂