2

我的 sqlite 准备语句遇到了一些困难。我收到一条错误消息,说我的表不存在,尽管我已经在多个地方检查过它,它确实存在,所以我很困惑。

  • 该文件位于正确的 iPhone 模拟器应用程序文件夹中
  • 该文件已添加到我的项目中,并可在项目导航器中查看
  • 它也在我的构建阶段——复制捆绑资源区域。
  • 我已经清理干净并再次开始跑步。
  • 数据库存在并且运行我的 sql 语句让我得到我预期的结果。

    - (NSMutableArray *) getMyWorkout{
    NSMutableArray *workoutArray = [[NSMutableArray alloc] init];
    @try {
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    
    NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:@"IOSDB.sqlite"];
        NSLog(@"Db path is %@",dbPath);
    BOOL success = [fileMgr fileExistsAtPath:dbPath];
    
    if(!success) {
        NSLog(@"Cannot locate database file '%@'.", dbPath);
    }
    
    if(!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK)){
        sqlite3_close(db);
        NSLog(@"Failed to open database with message '%s'.", sqlite3_errmsg(db));
    }
    
    const char *sql = "SELECT Id, type, difficulty, duration, description FROM workoutTbl";
    sqlite3_stmt *sqlStatement;
    
    if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK){
    
    NSLog(@"%s Prepare failure '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(db), sqlite3_errcode(db));
    }        //...
    

当我运行它时,我得到文件路径和以下错误

    2013-02-01 18:07:08.060 TriShake[9251:c07] -[MyWorkoutList getMyWorkout] Prepare failure 'no such table: workoutTbl' (1)

我已经检查了这些其他问题,但无法找到解决方案

我知道如果数据库路径不存在,sqlite3_open() 会为您创建一个空数据库,但我知道它存在,所以随之而来的是挫败感。您能给我的任何帮助或指导将不胜感激。

4

3 回答 3

6

就您当前的问题而言,这将是一件简单的事情。

  1. 您说您已经“清理并再次构建”,但您是否真的从模拟器中删除了旧应用程序?手动删除应用程序,或者更简单,通过从“iOS 模拟器”菜单中选择“重置内容和设置”来完全重置模拟器。有时 Xcode 并不擅长知道要复制哪些文件(尤其是在这种情况下,您在设备上运行它可能会更改模拟器捆绑包中文件的时间戳!)

  2. 再次运行应用程序。

  3. 如果应用程序没有按预期运行,请从 Mac 上打开模拟器文件夹中的数据库并检查数据库以确保表在那里并且与您预期的一样。sqlite3所以导航到应用程序,打开捆绑包(您可能必须选择“显示包内容”选项),确认数据库的存在,但同样重要的是,在您最喜欢的 Mac工具中打开这个特定的数据库副本选择并确认那里的表的存在。

让我们知道你发现了什么。同样,它必须是一些简单的东西,例如:

  • 也许重建应用程序的过程并不是重新安装所有东西;我偶尔会遇到 Xcode 在我的模拟器上安装期间选择不重新复制某些内容的问题;

  • 也许您的项目中的数据库不小心放在了子目录中,更糟糕的是,您可能有两个副本位于不同的目录中;

  • 也许您的 Xcode 项目中的数据库在表或文件的名称中丢失(或有错字或(尤其是在设备的情况下)文件名大写不正确);

  • 等等。

对于许多此类错误,在完全重置模拟器本身之前,您不会注意到问题。它可能是一百万件小事,但希望完全重置模拟器并重新开始将帮助您找到问题。当涉及到这类问题时,它总是很简单。


其他一些小观察:

  1. 您可能不应该从捆绑包中打开数据库。以编程方式将其从捆绑包复制到Documents文件夹,然后从那里打开数据库。我知道这似乎没有必要,但出于多种原因,这很重要(如果 db 在应用程序运行期间发生更改,如果 db 意外在您身上创建,请不要让 Xcode 对更改的内容感到困惑(即使只是文件时间戳)在 Xcode 背后更改的捆绑包中,等等)

  2. 如果您需要数据库在那里,您应该使用sqlite3_open_v2,使用 SQLITE_OPEN_READWRITE 或 SQLITE_OPEN_READONLY 作为标志(但包括SQLITE_OPEN_CREATE)。让 sqlite 有机会为您创建空白数据库或以其他方式修改它会让人头疼,所以永远不要给它机会。

于 2013-02-02T02:40:11.640 回答
1

我遇到了和你一样的问题。如果IOS找不到指定的数据库文件,默认会为你创建一个,而不是报错。因此,您必须打开 IOS 为您创建的数据库文件,该文件是空白的,因此它当然包含您期望的表。我处理它: 1 你必须将名为 *.sqlite3 的资源文件捆绑到你的项目中 2 然后你必须使用 [NSBundle mainBundle] pathFordirectory...... 函数来搜索你正确的数据库文件。然后你就可以打开你期望的数据库文件并且可以正常操作了

此致,

于 2014-05-02T01:55:35.783 回答
1

没有足够的代表评论杰克的帖子,但这对我有帮助。

就我而言,我输入了错误的资源扩展路径:

// Wrong
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:@"productList"
                                                         ofType:@"sqlite3"];

// Should have been (added db ext)
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:@"productList"
                                                     ofType:@"db"];

我总是能通过:

if (sqlite3_open([sqLiteDb UTF8String], &_database) == SQLITE_OK))

因为它会自动为我创建一个 db 文件。

于 2015-02-23T16:54:53.217 回答