添加到SQLite数据库时禁止重复

时间:2018-05-30 14:17:07

标签: java android sqlite android-sqlite

我目前有一个学生成绩/班级输入课程,该课程接受以下输入:学生证,姓名,姓氏,班级ID,班级姓名,成绩点和字母等级。

出于显而易见的原因,我想限制用户输入相同学生/课程(学生ID,班级ID)对的重复记录,以及相同学生ID和名字/姓氏的重复记录。 (两名学生不应该填写相同的身份证。

目前我有一个非常基本的方法来添加这些数据,实现我的意图的最佳方法是什么?:

 db=openOrCreateDatabase("STUDENTGRADES", Context.MODE_PRIVATE, null);
    db.execSQL("CREATE TABLE IF NOT EXISTS CUSTOMER_TABLE(studentid VARCHAR, fname VARCHAR, lname VARCHAR, classid VARCHAR, classname VARCHAR, pointgrade INTEGER, lettergrade VARCHAR);");


    add.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            if(fname.getText().toString().trim().length()==0||
                    lname.getText().toString().trim().length()==0 || studentid.getText().toString().trim().length()==0)
            {
                showMessage("Error", "Please enter First & Last Name and Student ID");
                return;
            }
            db.execSQL("INSERT INTO CUSTOMER_TABLE VALUES('"+studentid.getText()+"','"+fname.getText()+"','"+lname.getText()+"','"+classid.getText()+"','"+classname.getText()+
                    "','"+pointgrade.getText()+"','"+lettergrade.getText()+"');");
            showMessage("Success", "Student Record added successfully");
            clearText();
        }
    });

2 个答案:

答案 0 :(得分:1)

当您使用包含所有信息的简单平面文件时,很容易让事情不同步。也就是说,与多个名称相关联的相同学生ID,或与多个类名相关联的相同类ID。如果需要更改学生姓名或班级名称,则需要额外的工作来保持同步。更不用说需要最小化重复记录。解决这个问题的第一步是重新设计您的数据库。对于你在这里提到的数据,我会使用三个表:

Students
ID            Name
------------  ---------------------------------
1             Henry
2             Molly
3             George

Classes
ID            Name
------------  --------------------------------
1             Ohio History
2             US History
3             World History

Grades
StudentID     ClassID       Grade         LetterGrade
------------  ------------  ------------  ------------
1             1             98            A
2             3             85            B
3             2             77            C
1             2             85            B
3             3             92            A

将学生和班级的主键设置为ID字段,将Grades设置为(StudentID,ClassID)的复合。这将阻止给定学生在同一课程中具有多个成绩,并且还将阻止多个学生具有相同的ID。类也一样。

现在,您的用户界面可以让用户选择学生,选择课程,然后分配成绩。可以计算或键入字母等级。

<小时/> 以下是我如何定义表格:

create table if not exists students (
  id          integer primary key autoincrement,
  last_name   varchar,
  first_name  varchar);

create table if not exists classes (
  id          integer primary key autoincrement,
  name        varchar);

create table if not exists grades (
  student_id    integer not null,
  class_id      integer not null,
  point_grade   integer,
  letter_grade  varchar,
  primary key (student_id, class_id),
  foreign key (student_id) references students,
  foreign key (class_id) references classes)
without rowid;

外键约束会阻止为不存在的学生或班级输入成绩,还会阻止学生或成绩分类被删除。如果学生或班级被删除,还有其他条款允许您删除学生或班级的所有成绩。

学生和班级之间的关系称为多对多关系。这意味着可以将许多学生分配到一个班级,并且可以将许多班级分配给单个学生。并不是说自动增量的唯一键是学生和班级ID。成绩文件中的ID引用相关的学生和班级行。在上面的数据示例中, 亨利有两个班级(俄亥俄州历史(98)和美国历史(85)),莫莉只有一个班级(世界历史(85)),乔治有两个班级(美国历史(77)和世界)历史(92))。

您可以创建一个结合学生班级和成绩的单一视图,如下所示:

create view if not exists student_view (
  last_name, first_name, class_name, point_grade, letter_grade)
as (
  select last_name, first_name, name, point_grade, letter_grade
    from students
      join grades on grades.student_id = students.id
      join classes on classes.id = grades.class_id;

答案 1 :(得分:1)

如果您不想替换此行,则可以将方法insertWithOnConflict CONFLICT_IGNORE 标记一起使用。如果没有相同的raw,则方法返回 -1 ,因此您可以处理它

<强>编辑:

首先,您需要创建UNIQUE行(在您的情况下 - 类ID和学生ID):

db.execSQL("CREATE TABLE YOURDB (" 
            + "_id INTEGER PRIMARY KEY AUTOINCREMENT, " 
            + "STUDENTID TEXT UNIQUE, " 
            + "CLASSID TEXT UNIQUE);"); 

然后为方法

的检查结果创建变量
int k = 0;

尝试插入值并将结果输入 k

try {
            SQLiteDatabase db = dbHelper.getWritableDatabase();
            k = db.insertWithOnConflict("YOURDB",null, contentValues, SQLiteDatabase.CONFLICT_IGNORE);

            db.close();
        }

并且,最后检查你的变量(我是在AsyncTask中完成的,因此检查方法位于 onPostExecute()方法中)

@Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        if (k==-1){
            Toast.makeText(getApplicationContext(), "Same raws", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getApplicationContext(), "not same raws", Toast.LENGTH_SHORT).show();
        }
    }

如果值重合,DataBase将不会更新,而 k 会获得 -1 值,因此,您可以制作Toast或其他东西来处理它< / p>

编辑2:

关于ContentValue初始化:

首先,您应该获取值,例如,您从editText获取它们:

String studentIdUpdate = studentEditText.getText().toString();
String classIdUpdate = classEditText.getText().toString();

然后创建ContentValues变量并将值放入其中

ContentValues contentValues = new ContentValues();
contentValues.put("STUDENTID", studentIdUpdate);
contentValues.put("CLASSID", classIdUpdate);