代码之家  ›  专栏  ›  技术社区  ›  ttattini

添加到sqlite数据库时不允许重复

  •  1
  • ttattini  · 技术社区  · 6 年前

    我目前有一个学生成绩/班级输入程序,它接受以下输入:学生ID、名字、姓氏、班级ID、班级名称、成绩点和字母成绩。

    出于明显的原因,我希望限制用户为同一个学生/课程(学生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 回复  |  直到 6 年前
        1
  •  1
  •   FIL201121    6 年前

    你可以用方法 insertWithOnConflict 具有 冲突忽略 标志,如果不想替换此行。如果没有相同的raw,则方法返回 - 1 ,所以你可以处理它

    编辑:

    首先,您需要创建唯一的行(在您的情况下-类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();
            }
        }
    

    如果值一致,则不会更新数据库, K 得到 - 1 价值,所以,你可以烤面包或其他东西来处理它

    编辑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);
    
        2
  •  1
  •   jmarkmurphy    6 年前

    当你使用一个包含所有信息的简单平面文件时,很容易使事情失去同步。也就是说,同一个学生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
    

    将student和classes上的主键设置为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;