1

我在 iPad 的 iOS 6 应用程序中使用了这个 sqlite3 表:

CREATE TABLE notes(id INTEGER PRIMARY KEY, note TEXT, noteDate TEXT, wasUploaded INTEGER);

从 sqlite3 命令行,此查询有效:

sqlite> Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `wasUploaded`=0;

1|Well|2012-10-04 22:46:23|0

在 iOS iPad 6.0 模拟器上,这些查询中的每一个都返回与上面完全相同的数据:

const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `id`=1";

const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `note`='Well'";

const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `noteDate`='2012-10-04 22:46:23'";

但是这个在命令行上运行良好的查询现在不返回任何数据:

const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `wasUploaded`=0";

有没有让我困惑。为什么最后一个查询不起作用?我是否需要将该列设为索引或其他内容?其他两个非索引列有效,但不是这个。

没有错误。最后一个不返回数据的查询给出的正常返回码为 101(sqlite3_step() 已完成执行),没有 where 子句的查询返回与其他三个查询相同的数据。

编辑:这是完整的代码

- (NSString *)getNotesToBeUploaded {
sqlite3 *stuDb;
NSString *thisNote;
NSMutableString *notes = [[NSMutableString alloc]init];

if (self.filePath == @"empty") {
    [self setDatabaseFilePath];
}

if (sqlite3_open([self.filePath UTF8String], &stuDb) == SQLITE_OK)
{
    // this is the query line that get changed to show stackoverflow the different results:
    const char *sqlStatement = "Select `id`,`note`,`noteDate` FROM notes WHERE `wasUploaded`=0";
    sqlite3_stmt *compiledStatement;
    int nResult = sqlite3_prepare_v2(stuDb, sqlStatement, -1, &compiledStatement, NULL);
    if ( nResult == SQLITE_OK)
    {
        int nret; // diagnostic used to watch return vaues when single stepping
        while ((nret = sqlite3_step(compiledStatement)) == SQLITE_ROW)
        {
            int id =  sqlite3_column_int(compiledStatement, 0);
            const unsigned char *note =  sqlite3_column_text(compiledStatement, 1);
            const unsigned char *noteDate =  sqlite3_column_text(compiledStatement, 2);
            int wu =  sqlite3_column_int(compiledStatement, 4);
            if (strlen((const char *)note) > 0 && strlen((const char *)noteDate) > 0)
            {
                thisNote = [NSString stringWithFormat:@"%d,%s,%s,%d\n",id, noteDate, note, wu];
                [notes appendString:thisNote];
            }
        }
    } else {
        sqlite3_finalize(compiledStatement);// prevent small memory leaks
        sqlite3_close(stuDb);
        thisNote =
        [NSString stringWithFormat:@"prepare failed with status:%d in %s at line %d path was %@,0,0\n",nResult,__FILE__,__LINE__,self.filePath];
        [notes appendString:thisNote];
        [notes appendString:@"\n"];
        return (NSString *)notes;
    }
    sqlite3_finalize(compiledStatement);
    sqlite3_close(stuDb);
}
4

1 回答 1

2

您是否正在检查sqlite3电话的返回码?并且,如果您没有得到SQLITE_OKSQLITE_ROW,则应酌情检查sqlite3_errmsg结果以诊断发生了什么。如果您希望我们帮助您,您真的应该分享您的代码。但首次使用 iOS SQLite 应用程序中最常见的问题是

  • 未能将数据库包含在您的应用程序包中。检查您的目标设置并确保您已将数据库包含在Build Phases. ~/Library/Application Support/iPhone Simulator您还可以通过在文件夹中的模拟器中查看您的应用程序包来确认这一点。如果您想这样做,您可能需要通过在终端命令行界面中~/Library输入来取消隐藏您的文件夹。chflags no hidden ~/Library

  • 如果您计划从应用程序更新数据库,则Documents在尝试开始使用它之前未能先将数据库从捆绑包复制到文件夹。

  • 使用sqlite3_open并解释成功的返回码作为数据库已成功打开的证据......但是如果它没有找到数据库,该sqlite3_open函数会烦人地创建一个新的空白数据库......我总是建议人们sqlite3_open_v2改用,其中如果没有找到它,如果这不是您想要的,您可以省略该参数以创建一个空白数据库。

当然,也可能存在大量与代码相关的问题(调用函数的顺序、未能检查返回码等)。没有看到代码就不可能进一步评论。

我觉得有义务分享我最后的 SQLite 编程建议,值得一试 FMDB Objective-C SQLite 包装库,它极大地简化了 iOS 中的 SQLite 编程。


更新:

查看您的代码后,它看起来不错。我只是运行它(仅调整为只是NSLog而不是附加注释):

- (void)test2
{
    sqlite3 *stuDb;
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *databaseName = [documentsDirectory stringByAppendingPathComponent:@"test.db"];

    if (sqlite3_open([databaseName UTF8String], &stuDb) == SQLITE_OK)
    {
        // this is the query line that get changed to show stackoverflow the different results:
        const char *sqlStatement = "Select `id`,`note`,`noteDate` FROM notes WHERE `wasUploaded`=0";
        sqlite3_stmt *compiledStatement;
        int nResult = sqlite3_prepare_v2(stuDb, sqlStatement, -1, &compiledStatement, NULL);
        if ( nResult == SQLITE_OK)
        {
            int nret; // diagnostic used to watch return vaues when single stepping
            while ((nret = sqlite3_step(compiledStatement)) == SQLITE_ROW)
            {
                int id =  sqlite3_column_int(compiledStatement, 0);
                const unsigned char *note =  sqlite3_column_text(compiledStatement, 1);
                const unsigned char *noteDate =  sqlite3_column_text(compiledStatement, 2);
                int wu =  sqlite3_column_int(compiledStatement, 4);
                if (strlen((const char *)note) > 0 && strlen((const char *)noteDate) > 0)
                {
                    // thisNote = [NSString stringWithFormat:@"%d,%s,%s,%d\n",id, noteDate, note, wu];
                    // [notes appendString:thisNote];
                    NSLog(@"%d,%s,%s,%d\n",id, noteDate, note, wu);
                }
            }
        } else {
            //sqlite3_finalize(compiledStatement);// prevent small memory leaks, not needed if the prepare failed
            sqlite3_close(stuDb);
            NSLog(@"prepare failed with error %s", sqlite3_errmsg(stuDb));
            return;
        }
        sqlite3_finalize(compiledStatement);
        sqlite3_close(stuDb);
    }
}

我得到了结果:

2012-10-05 15:44:06.075 test8[1574:c07] 1,2012-10-05 19:43:37,ABC,0
2012-10-05 15:44:06.076 test8[1574:c07] 2,2012-10-05 19:43:46,XYZ,0

所以问题一定出在数据库本身。从您上一条评论来看,听起来重建数据库是为您完成的。那太棒了。

于 2012-10-05T18:33:23.237 回答