我目前有一个学生成绩/班级输入课程,该课程接受以下输入:学生证,姓名,姓氏,班级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();
}
});
答案 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);