准备错误:没有这样的表:项目

时间:2013-10-16 12:38:13

标签: iphone ios objective-c c

这个函数向我显示错误“准备 - 错误#0:没有这样的表:项目 “。有人可以帮我解决这个错误。

- (void)viewDidLoad
    {
    [super viewDidLoad];
    const char *dbpath = [databasePath UTF8String];
    sqlite3_stmt *statement;

    if (sqlite3_open(dbpath, &contactDB)== SQLITE_OK)
    {
        NSString *querySQL = [NSString stringWithFormat:@"Select name FROM items"];
        const char *query_stmt = [querySQL UTF8String];

        if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
        { NSLog(@"Data not fetched");
            if (sqlite3_step(statement) == SQLITE_ROW)
            {NSLog(@"Prepare-error #%i: %s", (sqlite3_prepare_v2(contactDB, [querySQL  UTF8String], -1, &statement, NULL) == SQLITE_OK), sqlite3_errmsg(contactDB));
                NSString *namefeild = [[NSString alloc]initWithUTF8String:(const char *)  sqlite3_column_text(statement, 0)];
                [list objectAtIndex:namefeild];
            }
            else{
                NSLog(@"Data not fetched");
            }
            sqlite3_finalize(statement);
        }else {NSLog(@"Prepare-error #%i: %s", (sqlite3_prepare_v2(contactDB, query_stmt,  -1, &statement, NULL) == SQLITE_OK), sqlite3_errmsg(contactDB));}
        sqlite3_close(contactDB);
    }

这两个函数是n个不同的视图控制器。

在视图didload中创建数据库。

- (void)viewDidLoad
{
[super viewDidLoad];
NSString *docsDir;
NSArray *dirPath;
dirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,  YES);
docsDir = [dirPath objectAtIndex:0];
databasePath = [[NSString alloc]initWithString:[docsDir  stringByAppendingPathComponent:@"contactDB"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath] == NO) {
    const char *dbpath = [databasePath UTF8String];
    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) {
        char *errMsg;
        const char  *sql_stmt = "create table if not exists items(name varchar, price integer, description varchar)";
        if (sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
        {
            NSLog(@"Fail to create table");
        }
        sqlite3_close(contactDB);
    }else{
        NSLog(@"Failed to open database");
    }
}


}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

并在保存操作中将数据添加到数据库中。

- (IBAction)save:(id)sender {
sqlite3_stmt *statement;
const char *dbpath = [ databasePath UTF8String];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) {
    NSString *insertSQL = [NSString stringWithFormat:@"insert into items(name, price, description) values (\"%@\",\"%@\",\"%@\")", nametxt.text, pricetxt.text, description.text];
    const char *insert_stmt = [insertSQL UTF8String];
    sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);
    if (sqlite3_step(statement) == SQLITE_DONE)
    {
        NSLog(@"contact added");
        nametxt.text= @"";
        pricetxt.text = @"";
        description.text = @"";
    }else{
        NSLog(@"Failed to add contact");
    }
    sqlite3_finalize(statement);
    sqlite3_close(contactDB);
 }
}

2 个答案:

答案 0 :(得分:1)

通常,这意味着您打开的数据库中不存在该表。您应该在模拟器的Documents文件夹(~/Library/Application Support/iPhone Simulator)中找到该数据库,并在您选择的MacOS SQLite工具中打开它,亲自查看该表是否存在。我怀疑它不会在那里。

此问题的常见原因是databasePath处的文件不存在(例如,您可能在数据包中包含数据库副本,但不包含Documents文件夹),在这种情况下sqlite3_open将在databasePath静静地创建一个新的空白数据库。

假设您不希望它在找不到它时创建空白数据库,您应该:

  • 从模拟器/设备中删除您的应用程序(以便删除所有空白数据库);

  • 检查您的原始开放例程并使用NSFileManager检查数据库是否存在(如果数据库尚未存在)(可能在继续之前将数据库从包中复制到文档中);

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:databasePath]) {
        NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"itemsdb" ofType:@"sqlite"];
        [fileManager copyItemAtPath:bundlePath toPath:databasePath error:nil];
    }
    

    或者如果数据库不存在,您的代码可能会动态创建表,但想法是一样的。在打开文件之前检查文件是否存在。

  • 也许在将来,请考虑将sqlite3_open_v2SQLITE_OPEN_READWRITE选项一起使用(但 SQLITE_OPEN_CREATE选项),这不会创建数据库,如果找不到数据库,将报告错误。


说过上面的内容(当有人遇到像你这样的错误时,你应该知道“你应该知道的那些表”应该在那里时,这是一般的建议吗),你的代码示例中有一些特定的问题你处理错误报告:

  • 如果步骤成功,则表示您报告错误。当然,如果步骤失败,你只会这样做。

  • 由于步骤而产生的错误显示“准备错误”。当然应该是“步骤错误”。

  • 您的错误记录正在调用再次失败的函数以获取返回码。您应该在第一次调用该函数时保存返回代码,从而使您不必再次调用它来获取错误消息。 (这很重要,因为有时函数返回的值会改变并重置错误信息。不要再次调用失败的函数!)保存原始返回码也更有效。

因此:

if (sqlite3_open(dbpath, &contactDB)== SQLITE_OK)
{
    NSString *querySQL = [NSString stringWithFormat:@"Select name FROM items"];
    const char *query_stmt = [querySQL UTF8String];

    int rc;  // variable to hold the return code

    if ((rc = sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL)) == SQLITE_OK)
    {
        if ((rc = sqlite3_step(statement)) == SQLITE_ROW)
        {
            NSString *namefeild = [[NSString alloc]initWithUTF8String:(const char *)  sqlite3_column_text(statement, 0)];
            [list objectAtIndex:namefeild];
        }
        else {
            if (rc == SQLITE_DONE)
                NSLog(@"step found no data");
            else
                NSLog(@"step-error #%i: %s", rc, sqlite3_errmsg(contactDB));
        }
        sqlite3_finalize(statement);
    } else {
        NSLog(@"Prepare-error #%i: %s", rc, sqlite3_errmsg(contactDB));
    }
    sqlite3_close(contactDB);
}

答案 1 :(得分:1)

- (void)viewDidLoad
 {
    [super viewDidLoad];
    const char *dbpath = [databasePath UTF8String];

    NSLog("%@", databasePath);

    ...
    ...
}

将数据库路径复制到剪贴板并将其粘贴到控制台中。

  1. cd“[数据库路径]”
  2. sqlite3 database_filename.db
  3. 使用.dump
  4. 在.dump命令之后,您是否看到了表的创建语句?如果没有,那么您需要仔细检查实际创建数据库的位置。如果您使用.dump命令的内容更新答案,那将非常有用。