1

我正在使用 sqlite 编写一个简单的导航视图 iphone 程序用于学习目的。我以前在数据库中有一个表,但现在已将其更新为两个,我的 INNER JOIN 语句崩溃了。SQL 语句似乎可以直接运行它。在下面的代码中,未注释的语句工作得很好,但是如果我将它们切换出来,注释的语句会出现错误。

static sqlite3_stmt *init_statement = nil;
static sqlite3_stmt *dehydrate_statment = nil;

@implementation ICD9
@synthesize primaryKey,text,priority,status,match;

- (id)initWithPrimaryKey:(NSInteger)pk database:(sqlite3 *)db {

    if (self = [super init]) {
        primaryKey = pk;
        database = db;
        if (init_statement == nil) {
            const char *sql = "SELECT text,priority,complete FROM todo WHERE pk=?"; 
        //const char *sql = "SELECT todo.*, match.code10 FROM todo INNER JOIN match ON match.text = todo.text WHERE pk=1;";
        if (sqlite3_prepare_v2(database, sql, -1, &init_statement, NULL) != SQLITE_OK) {
                NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
        }
    }
    return self;
}

这些表在同一个数据库中:

CREATE TABLE todo(pk INTEGER PRIMARY KEY, text VARCHAR(25), priority INTEGER, complete BOOLEAN);
CREATE TABLE match(matchid INTEGER PRIMARY KEY, text VARCHAR(25), name VARCHAR(25));

我对此很陌生,因此将不胜感激。

4

1 回答 1

0

关键是检查返回的错误信息sqlite3_errmsg。您报告您的NSAssert线路报告消息:

未能准备带有消息“没有这样的表:匹配”的语句

这意味着您打开的数据库没有match表。如果你在模拟器上运行了这个,最简单的方法是在你选择的 MacOS SQLite 工具中打开数据库(我使用Base,你可以使用sqlite3命令行工具;使用任何你想要的工具)。该数据库可以在您的~/Library/Application Support/iPhone Simulator文件夹中找到。为了更容易找到此数据库,您可能希望~/Library通过启动Terminal应用程序然后运行命令来取消隐藏文件夹chflags nohidden ~/Library/

无论如何,我想您会发现该match表不存在(也许整个数据库将是空白的)。一个常见的原因是调用sqlite_open一个不存在的数据库,在这种情况下,它将为您创建一个空白数据库。

如果是这种情况,您希望

  • 删除您的 Documents 文件夹中可能拥有的所有空白数据库(最简单的方法是从您的设备/模拟器中删除该应用程序)并再次运行它;和

  • 检查您的数据库打开逻辑,它可能看起来像:

    NSString *filename = @"yourdb.sqlite";
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *bundlePath = [[NSBundle mainBundle] pathForResource:[filename stringByDeletingPathExtension] ofType:[filename pathExtension]];
    NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    NSString *path = [documentsPath stringByAppendingPathComponent:filename];
    
    if (![fileManager fileExistsAtPath:path isDirectory:NO])
    {
        NSError *error = nil;
        [fileManager copyItemAtPath:bundlePath toPath:path error:&error];
        NSAssert(error == nil, @"Unable to copy %@ to %@", bundlePath, path);
    }
    

    显然,这假设您已经准备好在您的包中使用的数据库。如果您正在以编程方式创建它,那么只需在 if 块内执行此操作,您确定它不是这种情况fileExistsAtPath

于 2013-10-29T19:24:43.613 回答