数据库由各个级别组成,每个级别由多个测验组成。
1级包括3个测验
2级有10个测验。等等...
1级还可以,那里应该有3个测验。
当我打开2级时,它会显示从1到10的测验,但是问题出在1-3个测验中前3个测验实际上是1级测验,然后从第4次测验到第10次测验,我的第2级进行了(剩下7个测验)。我忘记过滤的地方,还是做错了?
public class QuizDbHelper extends SQLiteOpenHelper {
.......skip here....
@Override
public void onConfigure(SQLiteDatabase db) {
super.onConfigure(db);
db.setForeignKeyConstraintsEnabled(true);
}
private void addJLPTLevel(JLPTLevel jlptLevel) {
ContentValues cv = new ContentValues();
cv.put(JLPTLevelsTable.COLUMN_NAME, jlptLevel.getName());
cv.put(JLPTLevelsTable.COLUMN_JLPTLevel_ID, jlptLevel.getLevelID());
db.insert(JLPTLevelsTable.TABLE_NAME, null, cv);
}
private void addQuizList(ListQuiz listQuiz) {
ContentValues cv = new ContentValues();
cv.put(QuizListTable.COLUMN_NAME, listQuiz.getName());
cv.put(QuizListTable.COLUMN_JLPTLevel_ID, listQuiz.getLevelID());
db.insert(QuizListTable.TABLE_NAME, null, cv);
}
private void addQuestion(Question question) {
ContentValues cv = new ContentValues();
cv.put(QuestionsTable.COLUMN_QUESTION, question.getQuestion());
cv.put(QuestionsTable.COLUMN_OPTION1, question.getOption1());
cv.put(QuestionsTable.COLUMN_OPTION2, question.getOption2());
cv.put(QuestionsTable.COLUMN_OPTION3, question.getOption3());
cv.put(QuestionsTable.COLUMN_OPTION4, question.getOption4());
cv.put(QuestionsTable.COLUMN_ANSWER_NB, question.getAnswerNB());
cv.put(QuestionsTable.COLUMN_QUIZ_LIST_ID, question.getListTest());
db.insert(QuestionsTable.TABLE_NAME, null, cv);
}
public ArrayList<ListQuiz> getNListQuiz(int NListID) {
ArrayList<ListQuiz> nQuizList = new ArrayList<>();
db = getReadableDatabase();
String selection = QuizListTable.COLUMN_JLPTLevel_ID + " = ? ";
String[] selectionArgs = new String[]{String.valueOf(NListID)};
Cursor c = db.query(
QuizListTable.TABLE_NAME,
null,
selection,
selectionArgs,
null,
null,
null
);
if (c.moveToFirst()) {
do {
ListQuiz nQuizLevel = new ListQuiz();
nQuizLevel.setId(c.getInt(c.getColumnIndex(QuizListTable._ID)));
nQuizLevel.setName(c.getString(c.getColumnIndex(QuizListTable.COLUMN_NAME)));
nQuizLevel.setLevelID(c.getInt(c.getColumnIndex(QuizListTable.COLUMN_JLPTLevel_ID)));
nQuizList.add(nQuizLevel);
} while (c.moveToNext());
}
c.close();
return nQuizList;
}
public ArrayList<Question> getNLevelQuestions(int quizListID) {
ArrayList<Question> questionList = new ArrayList<>();
db = getReadableDatabase();
String table = QuestionsTable.TABLE_NAME + "JOIN" + QuizListTable.TABLE_NAME +
" ON " + QuizListTable._ID + "=" + QuestionsTable.COLUMN_QUIZ_LIST_ID;
String[] columns = new String[]{
QuestionsTable._ID + " AS " + QuestionsTable.TABLE_NAME + "_" + QuestionsTable._ID,
QuestionsTable.COLUMN_QUIZ_LIST_ID,
QuizListTable._ID + " AS " + QuizListTable.TABLE_NAME + "_" + QuizListTable._ID,
QuizListTable.COLUMN_JLPTLevel_ID,
QuizListTable.COLUMN_NAME
};
String selection = QuestionsTable.COLUMN_QUIZ_LIST_ID + " = ? ";
String[] selectionArgs = new String[]{String.valueOf(quizListID)};
Cursor c = db.query(
QuestionsTable.TABLE_NAME,
columns,
selection,
selectionArgs,
null,
null,
null
);
if (c.moveToFirst()) {
do {
Question question = new Question();
question.setId(c.getInt(c.getColumnIndex(QuestionsTable._ID)));
question.setQuestion(c.getString(c.getColumnIndex(QuestionsTable.COLUMN_QUESTION)));
question.setOption1(c.getString(c.getColumnIndex(QuestionsTable.COLUMN_OPTION1)));
question.setOption2(c.getString(c.getColumnIndex(QuestionsTable.COLUMN_OPTION2)));
question.setOption3(c.getString(c.getColumnIndex(QuestionsTable.COLUMN_OPTION3)));
question.setOption4(c.getString(c.getColumnIndex(QuestionsTable.COLUMN_OPTION4)));
question.setAnswerNB(c.getInt(c.getColumnIndex(QuestionsTable.COLUMN_ANSWER_NB)));
question.setListTest(c.getInt(c.getColumnIndex(QuestionsTable.COLUMN_QUIZ_LIST_ID)));
questionList.add(question);
} while (c.moveToNext());
}
c.close();
return questionList;
}
}
QuizContractor.java
package com.hfad.jlpt1quiz;
import android.provider.BaseColumns;
public final class QuizContract {
private QuizContract() {
}
public static class JLPTLevelsTable implements BaseColumns{
public static final String TABLE_NAME = "test_level";
public static final String COLUMN_NAME = "LevelName";
public static final String COLUMN_JLPTLevel_ID = "LevelID";
}
public static class QuizListTable implements BaseColumns{
public static final String TABLE_NAME = "quiz_list";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_JLPTLevel_ID = "LevelID";
//QuizListTable._ID to QuestionsTable.COLUMN_QUIZ_LIST_ID
}
public static class QuestionsTable implements BaseColumns {
public static final String TABLE_NAME = "quiz_questions";
public static final String COLUMN_QUESTION = "question";
public static final String COLUMN_OPTION1 = "option1";
public static final String COLUMN_OPTION2 = "option2";
public static final String COLUMN_OPTION3 = "option3";
public static final String COLUMN_OPTION4 = "option4";
public static final String COLUMN_ANSWER_NB = "answer_nb";
//It should be foreign key for QuizListTable._ID
public static final String COLUMN_QUIZ_LIST_ID = "quiz_list_id";
}
}
测验水平
测验列表
测验问题
答案 0 :(得分:1)
您猜测外键的定义将根据定义的外键自动提取数据。事实并非如此。定义外键的全部作用是添加一个约束(规则),该约束必须遵循,即说要在表(子项)中插入引用另一个表必须的行(如果foreignKey Constraints Enabled为true)。因此,您必须加入表 ON 以从两个表中获取数据。
假设您有两个表
测验列表,其中有;
和问题,其中包含;
引用测验列表的列(因此引用级别)。
然后使用以下内容填充表:-
DROP TABLE IF EXISTS question;
DROP TABLE If EXISTS quizlist;
CREATE TABLE IF NOT EXISTS quizlist (ID INTEGER PRIMARY KEY, level INTEGER, name TEXT);
CREATE TABLE IF NOT EXISTS question (ID INTEGER PRIMARY KEY, question TEXT, quizlist_reference REFERENCES quizlist(id));
INSERT INTO quizlist (level,name) VALUES (1,'P 1'), (1,'P 2'),(1,'P 3'),(2,'P 4'),(2,'P 5'),(3,'P 6'),(3,'P 7');
INSERT INTO question (question, quizlist_reference) VALUES
('Q1',1),('Q2',6),('Q3',2),('Q4',4),('Q5',3),('Q6',1),('Q7',1),('Q8',1),('Q9',3),('Q10',3),('Q11',3),
('Q12',2),('Q13',4),('Q14',5),('Q15',3),('Q16',4),('Q17',6);
将产生两个表:-
测验表:-
问题:-
可以看出,没有级别和级别的名称未包括在内。相反,如果您使用来运行SELECT查询(仅用户友好的数据是问题,它是级别名称和级别):-
SELECT question, name, level
FROM question
JOIN quizlist ON quizlist.id = quizlist_reference
ORDER BY question ASC;
结果将是:-
现在是选择一个级别的所有问题的简单步骤,仅需一个WHERE子句,例如WHERE level = 1
包含在内。
所以使用:-
SELECT question
FROM question
JOIN quizlist ON quizlist.id = quizlist_reference
WHERE level = 1
ORDER BY question ASC;
将导致:-
类似地:-
SELECT question
FROM question
JOIN quizlist ON quizlist.id = quizlist_reference
WHERE level = 2
ORDER BY question ASC;
将导致:-
不可能在没有猜测的情况下提供更具体的答案,因为在问题中没有关于外键,列定义等的指示。因此,您将需要适当地应用所显示的原理。
请注意,要使用SQLiteDatabse query 方法,表和JOIN一起通过第一个参数作为字符串提供。
另外,如果您喜欢命名列(例如,在上面的示例中,两个表都有一个 id 列),则Cursor不包含表名,因此Cursor将具有相同名称的列和getColumnIndex方法不一定会获取正确的数据(我相信它将获取最后的此类列)。因此,建议使用AS子句为列指定特定的名称(这是第二个参数的一部分)。
这样,通过使代码适合于上述表格,可以使用以下方法在特定级别上提出问题:-
public ArrayList<Question> getQuestionsByLevel(int level) {
ArrayList<Question> questionList = new ArrayList<>();
db = getReadableDatabase();
String table = QuestionsTable.TABLE_NAME +
" JOIN " + QuizListTable.TABLE_NAME +
" ON " + QuizListTable.COLUMN_ID + "=" + QuestionsTable.COLUMN_QUESTIONS_QUIZ_LIST_REFERENCE;
String[] columns = new String[]{
QuestionsTable.COLUMN_ID +
" AS " + QuestionsTable.TABLE_NAME + "_" + QuestionsTable.COLUMN_ID, //<<<<<<<< make returned ID column (from questions table) unique name
QuestionsTable.COLUMN_QUESTION,
QuizListTable.COLUMN_ID +
" AS " + QuizListTable.TABLE_NAME + "_" + QuizListTable.COLUMN_ID, //<<<<<<<<<< make returned ID column (from quizlist table) unique name
QuizListTable.COLUMN_LEVEL,
QuizListTable.COLUMN_NAME
};
String selection = QuizListTable.COLUMN_QUIZ_LIST_LEVEL + "= ?";
String[] selectionArgs = new String[]{String.valueOf(quizListID)};
Cursor c = db.query(
table,
columns,
selection,
selectionArgs,
null,
null,
null
);
...............
SELECT question.id AS question_id,question,quizlist.id AS quizlist_id, level, name FROM question JOIN quizlist ON quizlist.id = quizlist_reference WHERE level = 2