JOIN不能在sqlite查询编译中工作

时间:2013-10-29 16:14:43

标签: ios iphone sqlite xcode3.2

我正在编写一个简单的导航视图iphone程序,使用sqlite进行学习。我之前在数据库中有一个表,但现在已将其更新为两个,并且我的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;
}

这些表位于同一个db:

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));

我对此很新,所以任何帮助都会受到赞赏。

1 个答案:

答案 0 :(得分:0)

关键是检查sqlite3_errmsg返回的错误消息。您报告的是NSAssert行报告了该消息:

  

未能准备包含消息'no such table:match'

的声明

这意味着您打开的数据库没有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不是这种情况。