从SQLite数据库生成随机输出

时间:2015-04-24 13:36:42

标签: java android sqlite

您好我目前有一个数据库,其中存储了5个问题和答案。我希望每次应用程序运行时随机输出三个问题。我有以下代码,但我的应用程序在加载时崩溃

public List<Question> getAllQuestions() {
        List<Question> quesList = new ArrayList<Question>();
        int nQuestions = 3; //select COUNT(*) from questions

        Random random = new Random();
        int id = random.nextInt(nQuestions);

        String selectQuery = "SELECT  id FROM " + TABLE_QUEST;
        dbase=this.getReadableDatabase();
        Cursor cursor = dbase.rawQuery(selectQuery, null);
        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Question quest = new Question();
                quest.setID(cursor.getInt(0));
                quest.setQUESTION(cursor.getString(1));
                quest.setANSWER(cursor.getString(2));
                quest.setOPTA(cursor.getString(3));
                quest.setOPTB(cursor.getString(4));
                quest.setOPTC(cursor.getString(5));
                quesList.add(quest);
            } while (cursor.moveToNext());{
                 id = random.nextInt(nQuestions);
            }
        }
        // return quest list
        return quesList;
    }

3 个答案:

答案 0 :(得分:1)

很抱歉,我写这个作为答案,但我没有权限为一个问题写评论,所以我想告诉你,首先你将永远成为前三个增加的问题之一一个随机问题,因为对于随机ID,您使用3 id = random.nextInt(nQuestions);代替nQuestions而不是questList.size()(对于您来说是3,您应该使用{{1}}并对其中的数字执行3次0到questList.size()

答案 1 :(得分:0)

问题是,您只能从表中选择所有条目的ID。

您的随机内容也会只选择问题0,1或2.您的随机内容应为random.nextInt(5),因为您有5个问题。

最后,这应该是一个循环,然后在您的查询中添加多个轮询以获得多个问题。

String query = "SELECT * FROM " + TABLE_QUEST + " WHERE ";
    for (int x = 0; x < nQuestions; x++) {
        if (x > 0) {
            query += " OR ";
        }
        query += "id=" + random.nextInt(5);
    }

这将使您的查询如下所示:

SELECT * FROM TABLE_QUEST WHERE id=4 OR id=2 OR id=3

最后,改变你的cursor.moveToNext()的方式。您的代码应如下所示:

public List<Question> getAllQuestions() {
    List<Question> quesList = new ArrayList<Question>();
    int nQuestions = 3; //select COUNT(*) from questions

    Random random = new Random();

    String query = "SELECT * FROM " + TABLE_QUEST + " WHERE ";
    for (int x = 0; x < nQuestions; x++) {
        if (x > 0) {
            query += " OR ";
        }
        query += "id=" + random.nextInt(5);
    }

    dbase=this.getReadableDatabase();
    Cursor cursor = dbase.rawQuery(query, null);
    // looping through all rows and adding to list
    if (cursor.moveToFirst()) {
        do {
            Question quest = new Question();
            quest.setID(cursor.getInt(0));
            quest.setQUESTION(cursor.getString(1));
            quest.setANSWER(cursor.getString(2));
            quest.setOPTA(cursor.getString(3));
            quest.setOPTB(cursor.getString(4));
            quest.setOPTC(cursor.getString(5));
            quesList.add(quest);
        } while (cursor.moveToNext());
    }
    // return quest list
    return quesList;
}

答案 2 :(得分:0)

您的代码中存在一些错误。

首先,您的SQL查询错误:

String selectQuery = "SELECT  id FROM " + TABLE_QUEST;

为您提供表TABLE_QUEST中“id”列的所有值,而不是您通过调用Random.nextInt确定的id列。

String selectQuery = "SELECT * FROM " + TABLE_QUEST + " WHERE id=" + id;

“*”代表“此表中的所有列”,“WHERE”允许您根据后面的条件过滤行(即id = 3)。

注意虽然在这种情况下不是问题,但是传递未转义的值(即WHERE id=" + id部分是非常糟糕的形式,因为一旦您使用用户输入,它可能会使您容易受到SQL注入攻击这一点)。

第二:由于各种原因,其余代码没有多大意义。我会尝试列出一些:

  • 如果您的代码可以正常工作(即在SELECT中使用*代替id,但没有WHERE子句),您只需将数据库中的所有问题添加到列表中,因为没有条件。
  • 如果条件有效,你只会获得一行具有一定ID的行。你的do-while循环只运行一次。
  • 如果你在select周围有一个循环,那么它可能会起作用,但它可能会返回相同的行TWICE甚至更频繁。
  • 你还会因各种原因偶尔崩溃,其中包括
    • 主键 - 可能是自动递增的id属性 - 不一定在0..n-1范围内。它可能在你的情况下,但这不是典型的。自动递增主键通常从1开始。
    • 如果您的问题 - 答案记录是CRUD(创建,读取,更新,删除),则ID可能有漏洞,即“1,2,6,8,12”。

我会改写整个方法;有几种方法可以做到这一点。只是一些提示:

  1. 如果表中的记录非常少(例如少于几百个),您可以将所有问题加载到列表A中。
    1. 创建列表A
    2. 将数据库中的所有记录添加到列表A
    3. 创建列表B
    4. 只要列表B中的元素少于您想要的(即listB.size() < 3),就从列表A中删除一个随机元素并将其添加到列表B中。
    5. 返回列表B. //这看起来很浪费,但在你的情况下可能会好的。
  2. 让数据库进行随机化:
    1. SELECT * FROM table ORDER BY RANDOM()LIMIT 3;
    2. 将所有记录读入列表
    3. 返回列表
    4. 完成! (注意:这适用于sqlite,但据我所知,不是被不同的数据库系统普遍接受)。
  3. 有无数其他方法可以实现您的目标。但我只是使用ORDER BY RANDOM() LIMIT x技巧,这可能是最简单的方法。