【问题标题】:How can I get the DB to stop overwriting previous records?如何让数据库停止覆盖以前的记录?
【发布时间】:2018-12-14 00:24:59
【问题描述】:

所以在图片中,每次用户完成测验时,整个分数列都会被覆盖。我不太确定我应该使用哪种方法来单独保存分数。我也尝试更新而不是插入,但没有运气。我正在使用共享首选项来保存最高分并继续显示。但我也想将其实现到数据库中。

MyDataBaseHelper.java

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Debug;
import android.util.Log;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

// class to provide operations with database

public class MyDataBaseHelper extends SQLiteOpenHelper {

    // Database name
    public static String DATABASE_QUESTION = "QUIZ.db";
    // Current version of database
    private static final int DATABASE_VERSION = 1;
    // Database table name
    private static final String TABLE_QUESTION = "QuestionBank";
    private static final String TABLE_USER = "Users";
    // All fields used in question table
    private static final String KEY_ID_QUESTION = "id";
    private static final String QUESTION = "question";
    private static final String CHOICE1 = "choice1";
    private static final String CHOICE2 = "choice2";
    private static final String CHOICE3 = "choice3";
    private static final String CHOICE4 = "choice4";
    private static final String ANSWER = "answer";

    // All fields used in user table
    private static final String KEY_ID_USERS = "id";
    private static final String USER_NAME = "name";
    private static final String USER_SCORE = "score";

    // Question Table Create Query in this string
    private static final String CREATE_TABLE_QUESTION = "CREATE TABLE "
            + TABLE_QUESTION + "(" + KEY_ID_QUESTION
            + " INTEGER PRIMARY KEY AUTOINCREMENT," + QUESTION + " TEXT,"
            + CHOICE1 + " TEXT, " + CHOICE2 + " TEXT, " + CHOICE3 + " TEXT, "
            + CHOICE4 + " TEXT, " + ANSWER + " TEXT);";

    // User Table Query
    private static final String CREATE_TABLE_USER = "CREATE TABLE " + TABLE_USER + "(" + KEY_ID_USERS
            + " INTEGER PRIMARY KEY AUTOINCREMENT," + USER_NAME + " TEXT, " + USER_SCORE + " INTEGER);";

    public MyDataBaseHelper(Context context) {
        super(context, DATABASE_QUESTION, null, DATABASE_VERSION);
    }


    /**
     * This method is called by system if the database is accessed but not yet
     * created.
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d("DBHelper", "Created db");
        Log.d("DBHelper", CREATE_TABLE_QUESTION);
        db.execSQL(CREATE_TABLE_QUESTION); // create question table
        db.execSQL(CREATE_TABLE_USER);
    }

    /**
     * This method is called when any modifications in database are done like
     * version is updated or database schema is changed
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldvers, int newvers) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_QUESTION);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER);
        onCreate(db);
    }

    /**
     * This method is used to add question detail in question Table
     */
    public long addInitialQuestion (Question question) {
        SQLiteDatabase db = this.getWritableDatabase();
        // Creating content values
        ContentValues values = new ContentValues();
        values.put(QUESTION, question.getQuestion());
        values.put(CHOICE1, question.getChoice(0));
        values.put(CHOICE2, question.getChoice(1));
        values.put(CHOICE3,  question.getChoice(2));
        values.put(CHOICE4,  question.getChoice(3));
        values.put(ANSWER, question.getAnswer());
        // insert row in question table
        long insert = db.insert(TABLE_QUESTION, null, values);
        return insert;
    }

    /**
     * To extract data from database and save it Arraylist of data type
     * Question
     */
    public List<Question> getAllQuestionsList() {
        List<Question> questionArrayList = new ArrayList<>();
        String selectQuery = "SELECT  * FROM " + TABLE_QUESTION;

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor c = db.rawQuery(selectQuery, null);

        // looping through all records and adding to the list
        if (c.moveToFirst()) {
            do {
                Question question = new Question();

                String questText= c.getString(c.getColumnIndex(QUESTION));
                question.setQuestion(questText);

                String choice1Text= c.getString(c.getColumnIndex(CHOICE1));
                question.setChoice(0,choice1Text);

                String choice2Text= c.getString(c.getColumnIndex(CHOICE2));
                question.setChoice(1,choice2Text);

                String choice3Text= c.getString(c.getColumnIndex(CHOICE3));
                question.setChoice(2,choice3Text);

                String choice4Text= c.getString(c.getColumnIndex(CHOICE4));
                question.setChoice(3,choice4Text);

                String answerText= c.getString(c.getColumnIndex(ANSWER));
                question.setAnswer(answerText);

                // adding to Questions list
                questionArrayList.add(question);
            } while (c.moveToNext());
            Collections.shuffle(questionArrayList);
        }
        return questionArrayList;
    }

    public List<User> getAllUser(){
        String sortOrder = "SELECT * FROM " + TABLE_USER + " ORDER BY " + USER_SCORE + " DESC";
        List<User> userList = new ArrayList<User>();

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor c = db.rawQuery(sortOrder, null);
        if(c.moveToFirst()){
            User user = new User();
        }
        return userList;
    }

    public void addUser(User user) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(USER_NAME, user.getName());
        // Inserting Row
        db.insert(TABLE_USER, USER_NAME, values);
        db.close();

    }

    public void updateUser(User user) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(USER_NAME, user.getName());
        // updating row
        db.update(TABLE_USER, values, USER_NAME + " = ?",
                new String[]{String.valueOf(user.getId())});
        db.close();
    }

    public void deleteUser(User user) {
        SQLiteDatabase db = this.getWritableDatabase();
        // delete user record by id
        db.delete(TABLE_USER, USER_NAME + " = ?",
                new String[]{String.valueOf(user.getId())});
        db.delete(TABLE_USER, USER_SCORE + " = ?",
                new String[]{String.valueOf(user.getId())});
        db.close();
    }

    public boolean hasUser(String user){

        String searchQuery = "SELECT * FROM " + TABLE_USER + " WHERE " + USER_NAME + " = '" + user + "'";

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor c = db.rawQuery(searchQuery, null);
        c.moveToFirst();

        if (c.getCount() > 0) {
            c.close();
            db.close();
            return true;
        } else {
            c.close();
            db.close();
            return false;
        }
    }

    public void addScore(int point){
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(USER_SCORE, point);
        // Inserting Row
        db.update(TABLE_USER, values,null , null);
        db.close();
    }

}

测验活动.java

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

public class QuizActivity extends AppCompatActivity {

    private QuestionBank mQuestionLibrary = new QuestionBank();

    private TextView mScoreView;   // view for current total score
    private TextView mQuestionView;  //current question to answer
    private Button mButtonChoice1; // multiple choice 1 for mQuestionView
    private Button mButtonChoice2; // multiple choice 2 for mQuestionView
    private Button mButtonChoice3; // multiple choice 3 for mQuestionView
    private Button mButtonChoice4; // multiple choice 4 for mQuestionView

    private String mAnswer;  // correct answer for question in mQuestionView
    private int mScore = 0;  // current total score
    private int mQuestionNumber = 0; // current question number

    private String username = "";

    MyDataBaseHelper myDataBaseHelper;

    private static final String KEY_QUESTION_NUMBER = "questionNumber";
    private static final String KEY_SCORE = "currentScore";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_quiz);
        // setup screen for the first question with four alternative to answer
        mScoreView = (TextView)findViewById(R.id.score);
        mQuestionView = (TextView)findViewById(R.id.question);
        mButtonChoice1 = (Button)findViewById(R.id.choice1);
        mButtonChoice2 = (Button)findViewById(R.id.choice2);
        mButtonChoice3 = (Button)findViewById(R.id.choice3);
        mButtonChoice4 = (Button)findViewById(R.id.choice4);


        Intent intent = getIntent();
        username = intent.getStringExtra("username");

        myDataBaseHelper = new MyDataBaseHelper(this);

        mQuestionLibrary.initQuestions(getApplicationContext());

        if(savedInstanceState != null){
            mScore = savedInstanceState.getInt(KEY_SCORE,0);
            mQuestionNumber = savedInstanceState.getInt(KEY_QUESTION_NUMBER, 0) - 1;
        }

        updateQuestion();
        // show current total score for the user
        updateScore(mScore);
    }

    private void updateQuestion(){
        // check if we are not outside array bounds for questions
        if(mQuestionNumber<mQuestionLibrary.getLength() ){
            // set the text for new question,
            // and new 4 alternative to answer on four buttons
            mQuestionView.setText(mQuestionLibrary.getQuestion(mQuestionNumber));
            mButtonChoice1.setText(mQuestionLibrary.getChoice(mQuestionNumber, 1));
            mButtonChoice2.setText(mQuestionLibrary.getChoice(mQuestionNumber, 2));
            mButtonChoice3.setText(mQuestionLibrary.getChoice(mQuestionNumber, 3));
            mButtonChoice4.setText(mQuestionLibrary.getChoice(mQuestionNumber,4));
            mAnswer = mQuestionLibrary.getCorrectAnswer(mQuestionNumber);
            mQuestionNumber++;
        }
        else {
            Toast.makeText(QuizActivity.this, "It was the last question!", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(QuizActivity.this, HighScoreActivity.class);
            intent.putExtra("score", mScore); // pass the current score to the second screen
            intent.putExtra("username", username);
            myDataBaseHelper.addScore(mScore);
            startActivity(intent);
        }
    }

    // show current total score for the user
    private void updateScore(int point) {
        mScoreView.setText(""+mScore+"/"+mQuestionLibrary.getLength());
    }

    public void onClick(View view) {
        //all logic for all answers buttons in one method
        Button answer = (Button) view;
        // if the answer is correct, increase the score
        if (answer.getText().equals(mAnswer)){
            mScore = mScore + 1;
            Toast.makeText(QuizActivity.this, "Correct!", Toast.LENGTH_SHORT).show();
        }else
            Toast.makeText(QuizActivity.this, "Wrong!", Toast.LENGTH_SHORT).show();
        // show current total score for the user
        updateScore(mScore);
        // once user answer the question, we move on to the next one, if any
        updateQuestion();
    }

    @Override
    protected void onResume() {
        super.onResume();
        /*
        MyDataBaseHelper dataBaseHelper = new MyDataBaseHelper((this));
        List<Question> questions = dataBaseHelper.getAllQuestionsList();
        if(questions.isEmpty())
        {
            Log.d("QuizActivity", "List is empty");
        }        dataBaseHelper.addInitialQuestion(new Question("1. When did Google acquire Android ?",
                new String[]{"2001", "2003", "2004", "2005"}, "2005"));
                */
    }

    @Override
    protected void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putInt(KEY_SCORE, mScore);
        savedInstanceState.putInt(KEY_QUESTION_NUMBER, mQuestionNumber);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mScore = savedInstanceState.getInt(KEY_SCORE,0);
        mQuestionNumber = savedInstanceState.getInt(KEY_QUESTION_NUMBER, 0);
    }
}

HighScoreActivity.java

import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class HighScoreActivity extends AppCompatActivity  {

    private String username;
    private TextView txtScore;
    private TextView txtHighScore;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_highest_score);

         txtScore = (TextView) findViewById(R.id.textScore);
         txtHighScore = (TextView) findViewById(R.id.textHighScore);

        Intent intent = getIntent();
        int score = intent.getIntExtra("score",0);
        username = intent.getStringExtra("username");

        txtScore.setText(username + "'s Score: " + score);
//
//        SharedPreferences mypref = getPreferences(MODE_PRIVATE);
//        int highscore = mypref.getInt("highscore", 0);
//        if (highscore >= score){
//            txtHighScore.setText("High Score: " + highscore);
//        }
//        else {
//            txtHighScore.setText("New High Score: " + score);
//            SharedPreferences.Editor editor = mypref.edit();
//            editor.putInt("highscore", score);
//            editor.commit();
//        }

    }

    public void onClick(View view) {
        Intent intent = new Intent(HighScoreActivity.this, QuizActivity.class);
        intent.putExtra("username", username);
        startActivity(intent);

    }

    public void logOutOnClick(View view) {

        Intent intent = new Intent(HighScoreActivity.this, LoginActivity.class);
        startActivity(intent);
        finish();

    }
}

【问题讨论】:

    标签: java android sql sqlite


    【解决方案1】:

    我相信以下内容符合您的需要。

    更改后的签名,以便您可以传递要更新的用户的 ID、where 子句(不带 WHERE 关键字)和要在 where 子句中使用的参数。

    如果没有 where 子句,更新方法将更新所有行。(我认为这是您的核心问题)

    因此,您在数据库助手(SQLiteOpenHelper 的子类)中的代码可能是:-

    public void addScore(String username, int point){ //<<<<<<<<<< Changed signature
        SQLiteDatabase db = this.getWritableDatabase();
        String whereclause = USER_NAME + "=?"; //<<<<<<<<<< Added
        String[] whereargs = new String[]{username}; //<<<<<<<<<< Added
        ContentValues values = new ContentValues();
        values.put(USER_SCORE, point);
        // Inserting Row
        db.update(TABLE_USER, values, whereclause, whereargs);
        db.close();
    }
    

    然后您需要使用 myDataBaseHelper.addScore(username,mScore); 调用 addScore

    • 请注意,这不会添加分数,而是将其更改为传递的值。
    • 以上代码为in-principal code,未经测试,可能有一些错误。

    更新分数

    (即添加到现有分数(如果提供负值,则减去))

    public void addScore(String username, int points_to_add) {
        SQLiteDatabase db = this.getWritableDatabase();
        String sql = "UPDATE " + TABLE_USER + " SET " + USER_SCORE + " = " + USER_SCORE + "+? WHERE " + USER_NAME + "=?";
        String[] args = new String[]{String.valueOf(points_to_add), username};
        db.execSQL(sql,args);
        db.close();
    }
    
    • 已使用 execSQL,因为您无法传递项目名称(例如,通过内容值的列名称(insert 方法的限制))。

    示例

    考虑到上面的 addScore 方法和自定义(为了便于测试) addUser 方法(只需传递一个字符串作为用户名并将分数设置为 0):-

        mDBHlpr = new MyDataBaseHelper(this);
    
        // Add some users (Score will be 0)
        mDBHlpr.addUser("Fred");
        mDBHlpr.addUser("Bert");
        mDBHlpr.addUser("Mary");
        mDBHlpr.addUser("Sue");
    
        mDBHlpr.addScore("Fred",1200);
        mDBHlpr.addScore("Sarah",50000); // non-existant user
        mDBHlpr.addScore("Mary",6000);
        mDBHlpr.addScore("Mary", -2000);
        mDBHlpr.addScore("Sue", -1000);
        mDBHlpr.addScore("Bert", -1700);
    
        SQLiteDatabase db = mDBHlpr.getWritableDatabase();
        Cursor csr = db.query("Users",null,null,null,null,null,null);
        DatabaseUtils.dumpCursor(csr);
        csr.close();
        db.close();
    

    那么期望是:-

    • Fred 得分为 1200
    • Bert 的得分为 - 1700
    • Mary 的分数为 6000,然后降低 2000 到 4000
    • Sue 的得分为 -1000
    • Sarah,因为用户不存在,所以不会导致任何操作或失败

    dumpCursor 方法将转储光标(所有用户行)结果为(如预期):-

    I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@534a4524
    I/System.out: 0 {
    I/System.out:    id=1
    I/System.out:    name=Fred
    I/System.out:    score=1200
    I/System.out: }
    I/System.out: 1 {
    I/System.out:    id=2
    I/System.out:    name=Bert
    I/System.out:    score=-1700
    I/System.out: }
    I/System.out: 2 {
    I/System.out:    id=3
    I/System.out:    name=Mary
    I/System.out:    score=4000
    I/System.out: }
    I/System.out: 3 {
    I/System.out:    id=4
    I/System.out:    name=Sue
    I/System.out:    score=-1000
    I/System.out: }
    I/System.out: <<<<<
    

    【讨论】:

    • 我将如何处理它只是更新以前的分数而不是添加它?我最初的问题是,每次用户进行测验时,所有记录都会显示最后一个完成测验的用户的结果。但是,您提供的 addScore 方法确实解决了部分问题。
    • @SnehP 根据后面的第一段代码因此,您在数据库助手(SQLiteOpenHelper 的子类)中的代码可能是:-
    • 啊它确实有效!谢谢!因此,为了将内容传递给 sqlite 方法,我需要使用 .execSQL() 来执行查询?
    • @SnehP no 使用 execSQL 的唯一原因是您不能在便捷方法中包含列名。你需要说数量 = 数量 + score_value。如果内容值为cv.put("quantity","quantity +" + String.valueOf(score));,则生成的sql 将为quantity = 'quantity + 1000',数量列的值为quantity + 1000(即包含列名)。因此,在这种情况下,您必须自己编写 SQL,然后使用 execSQL(或其他类似方式)。要在没有表达式的情况下设置特定值,update 方法很好。
    • @SnehP 您的主要问题是 UPDATE 将更新所有行,除非您明确告诉它要更新哪些行(即通过 WHERE 子句) .
    猜你喜欢
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 2020-02-21
    相关资源
    最近更新 更多