从iPhone应用程序中读取数据库

时间:2015-04-20 17:50:23

标签: ios objective-c database xcode sqlite

以下是我从数据库中读取的代码:

if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
    const char *query_stmt = "SELECT QuestionID, question, RightAnswer,WrongAnswer1, WrongAnswer2, audio FROM questions WHERE done='no' AND Catagory='%@'", Catagory;

    int check = (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL));
    NSLog(@"%i",check);


    if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {

        while(sqlite3_step(statement) == SQLITE_ROW)
        {
            questionID = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
            questionString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
            rightAnswerString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
            wrong1AnswerString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
            wrong2AnswerString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
            audioInteger = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)];
            break;
        }

        sqlite3_finalize(statement);
    }
    sqlite3_close(database);
}

我想在我的表的第一行中读取done='no',并且类别与存储在变量catagory中的类别相匹配。我以为我可以使用while语句然后在循环之前断开。但是,永远不会满足while语句的条件。这告诉我,sql语句没有返回任何值。

数据库的SQL如下:

DROP TABLE IF EXISTS "Questions";
CREATE TABLE "Questions" ("QuestionID" INTEGER PRIMARY KEY  NOT NULL , "Question" TEXT, "RightAnswer" TEXT, "WrongAnswer1" TEXT, "WrongAnswer2" TEXT, "Done" BOOL, "Catagory" TEXT, "Audio" INTEGER);
INSERT INTO "Questions" VALUES(1,'What is the BPM of this piece?','120 BPM','70 BPM','170 BPM','no','Rhythm',1);
INSERT INTO "Questions" VALUES(2,'How far apart are the 2 notes the bass guitar plays?','4 Semitones','1 Semitone','6 Tones','no','Pitch',1);
INSERT INTO "Questions" VALUES(3,'How is the organ Panned?','Left','Right','Centre','no','Pan',1);
INSERT INTO "Questions" VALUES(4,'What are the note values of the HiHat rhythms?','Semi quaver','Quaver','Crotchet','no','Rhythm',1);
INSERT INTO "Questions" VALUES(5,'The first chord played on the organ is...','Minor','Major','Atonal','no','Pitch',1);
INSERT INTO "Questions" VALUES(6,'How is the bass sound panned in this piece?','Right','Left','Center','no','Pan',2);
INSERT INTO "Questions" VALUES(7,'How is the lead synth panned in this piece?','Left','Right','Center','no','Pan',2);
INSERT INTO "Questions" VALUES(8,'The Kick Drum Rhythm In this can abe described as...','Four to the Floor','Off beat','Minor','no','Rhythm',2);
INSERT INTO "Questions" VALUES(9,'A clap sound can be heard on beat..','2 and 4','1 and 3','3','no','Rhythm',2);
DROP TABLE IF EXISTS "Results";
CREATE TABLE "Results" ("ResultID" INTEGER PRIMARY KEY  NOT NULL , "QuestionRight" INTEGER, "TotalQuestions" INTEGER, "Catagory" TEXT);

所以我要问的是:

1)有没有更好的方法只读取满足我的sql语句的第一行?

2)我目前的方法是否有效?

感谢您的帮助,

*************更新*************

这是定义类别的地方:

CatagoryLoaded = [[NSUserDefaults standardUserDefaults] integerForKey:@"catagorysaved"];
switch (CatagoryLoaded) {
    case 1:
        CatagorySelected.text = [NSString stringWithFormat:@"Pan!"];
        Catagory = @"pan";
        break;
    case 2:
        CatagorySelected.text = [NSString stringWithFormat:@"Pitch!"];
         Catagory = @"pitch";
        break;
    case 3:
        CatagorySelected.text = [NSString stringWithFormat:@"Rhythm!"];
        Catagory = @"rhythm"; 
        break;
    default:
        break;
}

*************更新2 *************

我按照您的建议将其更改为限制1,现在正在获取thread1: signal SIGABRT

if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
    const char *query_stmt = "SELECT * FROM Questions WHERE Done='no' AND Catagory='%@' LIMIT 1", Catagory;

    int check = (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL));
    NSLog(@"%i",check);


    if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {


            questionID = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
            questionString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
            rightAnswerString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
            wrong1AnswerString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
            wrong2AnswerString = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
            audioInteger = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)];


        sqlite3_finalize(statement);
    }
    sqlite3_close(database);
}

*************更新************* 看起来声明将其保留为'%@'而不是存储在类别中的任何内容,任何想法为什么?

下面是一个屏幕截图的链接,显示SIGABRT崩溃前的变量。 (不会让我直接发布图片,因为我是网站新手)

http://puu.sh/hkOxf/8c05b9489b.png

1 个答案:

答案 0 :(得分:1)

我唯一的猜测是你的“类别”变量不是有效的。除此之外,SQL语句看起来不错。我不记得SQLite是否区分大小写,但将Done和Questions以及其他内容放在适当的情况下并没有什么坏处。

此外,出于性能原因,您始终可以在SQL语句末尾添加“限制1”以获取第一行。或者只是将其从WHILE更改为IF,因此它只运行一次,但是,我建议使用LIMIT语法。

NSString *query_stmt = [NSString stringWithFormat:"SELECT * FROM Questions WHERE Done='no' AND Catagory='%@' LIMIT 1", Catagory];