我建议您的架构只会导致您出现以下问题:-
我还建议您创建一些主所有列组合表的概念会导致您出现问题(例如,要获得下面显示的 overallgrade 结果可能需要大量编码才能完成使用这样的组合表作为源)
我建议对架构进行细微的更改,例如:-
CREATE TABLE IF NOT EXISTS STUDENT_TABLE (studentid TEXT, fname TEXT, lname TEXT);
CREATE TABLE IF NOT EXISTS CLASS_TABLE(classid TEXT PRIMARY KEY, classname TEXT UNIQUE);
CREATE TABLE IF NOT EXISTS GRADE_TABLE (studentid TEXT, classid TEXT, pointgrade INTEGER, lettergrade TEXT);
假设您随后使用以下内容插入了一些数据:-
INSERT INTO STUDENT_TABLE
VALUES('00001','Fred','Smith'),('00010','Mary','Thomas'),('00910','Angela','Jones')
;
INSERT INTO CLASS_TABLE VALUES('001','English'),('101','Mathematics'),('201','Chemistry');
INSERT INTO GRADE_TABLE VALUES
('00001','001',99,'A'), -- Fred Smith has 99 point grade as an A in English
('00001','101',25,'F'), -- Fred Smith has 25 point grade as an F on Mathematics
('00010','201',76,'B'), -- Angela Jones 76 a B in Chemistry
('00910','101',50,'C'),
('00910','201',63,'C'),
('00910','001',89,'A')
;
结果表将是:-
STUDENT_TABLE:-
CLASS_TABLE:-
GRADE_TABLE
然后,您可以使用 joins 来实现魔法,例如生成学生总分成绩列表(每个学生为所有班级添加的所有分数)以及他们所在的班级,例如:-
SELECT fname,
lname,
sum(pointgrade) AS overallgrade,
group_concat(classname,' - ') AS classes
FROM GRADE_TABLE
JOIN STUDENT_TABLE ON GRADE_TABLE.studentid = STUDENT_TABLE.studentid
JOIN CLASS_TABLE ON GRADE_TABLE.classid = CLASS_TABLE.classid
GROUP BY STUDENT_TABLE.studentid
ORDER BY overallgrade DESC
;
这会导致:-
要完全回答您的问题,但使用建议的架构,则以下 SQL 将相应地加入:-
SELECT
STUDENT_TABLE.studentid,
fname,
lname,
CLASS_TABLE.classid,
classname,
pointgrade,
lettergrade
FROM GRADE_TABLE
JOIN STUDENT_TABLE ON STUDENT_TABLE.studentid = GRADE_TABLE.studentid
JOIN CLASS_TABLE ON CLASS_TABLE.classid = GRADE_TABLE.classid;
这将导致以下结果:-
基于原始代码和建议的架构并利用此处提供的类Are there any methods that assist with resolving common SQLite issues?
注意上述代码只能运行一次,因为后续运行将导致 UNIQUE 约束冲突(又名 - 您不能将重复的行添加到 CLASS_TABLE)
以下代码:-
SQLiteDatabase db;
db=openOrCreateDatabase("STUDENTGRADES", Context.MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS STUDENT_TABLE (studentid TEXT, fname TEXT, lname TEXT)");
db.execSQL("CREATE TABLE IF NOT EXISTS CLASS_TABLE(classid TEXT PRIMARY KEY, classname TEXT UNIQUE)");
db.execSQL("CREATE TABLE IF NOT EXISTS GRADE_TABLE (studentid TEXT, classid TEXT, pointgrade INTEGER, lettergrade TEXT)");
db.execSQL("INSERT INTO STUDENT_TABLE \n" +
" VALUES('00001','Fred','Smith'),('00010','Mary','Thomas'),('00910','Angela','Jones')"
);
db.execSQL("INSERT INTO CLASS_TABLE VALUES('001','English'),('101','Mathematics'),('201','Chemistry');");
db.execSQL("INSERT INTO GRADE_TABLE VALUES\n" +
" ('00001','001',99,'A'), -- Fred Smith has 99 point grade as an A in English\n" +
" ('00001','101',25,'F'), -- Fred Smith has 25 point grade as an F on Mathematics\n" +
" ('00010','201',76,'B'), -- Angela Jones 76 a B in Chemistry\n" +
" ('00910','101',50,'C'), \n" +
" ('00910','201',63,'C'),\n" +
" ('00910','001',89,'A')\n" +
";");
Cursor csr = db.query("GRADE_TABLE JOIN STUDENT_TABLE ON STUDENT_TABLE.studentid = GRADE_TABLE.studentid JOIN CLASS_TABLE ON CLASS_TABLE.classid = GRADE_TABLE.classid",null,null,null,null,null,null);
CommonSQLiteUtilities.logDatabaseInfo(db);
CommonSQLiteUtilities.logCursorData(csr);
csr.close();
结果:-
05-31 04:20:32.605 3582-3582/? D/SQLITE_CSU: DatabaseList Row 1 Name=main File=/data/data/cpa.carpurchases/databases/STUDENTGRADES
Database Version = 0
Table Name = android_metadata Created Using = CREATE TABLE android_metadata (locale TEXT)
Table = android_metadata ColumnName = locale ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 0
Table Name = STUDENT_TABLE Created Using = CREATE TABLE STUDENT_TABLE (studentid TEXT, fname TEXT, lname TEXT)
Table = STUDENT_TABLE ColumnName = studentid ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 0
Table = STUDENT_TABLE ColumnName = fname ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 0
Table = STUDENT_TABLE ColumnName = lname ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 0
Table Name = CLASS_TABLE Created Using = CREATE TABLE CLASS_TABLE(classid TEXT PRIMARY KEY, classname TEXT UNIQUE)
Table = CLASS_TABLE ColumnName = classid ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 1
Table = CLASS_TABLE ColumnName = classname ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 0
Table Name = GRADE_TABLE Created Using = CREATE TABLE GRADE_TABLE (studentid TEXT, classid TEXT, pointgrade INTEGER, lettergrade TEXT)
Table = GRADE_TABLE ColumnName = studentid ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 0
Table = GRADE_TABLE ColumnName = classid ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 0
Table = GRADE_TABLE ColumnName = pointgrade ColumnType = INTEGER Default Value = null PRIMARY KEY SEQUENCE = 0
Table = GRADE_TABLE ColumnName = lettergrade ColumnType = TEXT Default Value = null PRIMARY KEY SEQUENCE = 0
05-31 04:20:32.609 3582-3582/? D/SQLITE_CSU: logCursorData Cursor has 12 rows with 9 columns.
Information for row 1 offset=0
For Column studentid Type is STRING value as String is 00001 value as long is 1 value as double is 1.0
For Column classid Type is STRING value as String is 001 value as long is 1 value as double is 1.0
For Column pointgrade Type is INTEGER value as String is 99 value as long is 99 value as double is 99.0
For Column lettergrade Type is STRING value as String is A value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00001 value as long is 1 value as double is 1.0
For Column fname Type is STRING value as String is Fred value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Smith value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 001 value as long is 1 value as double is 1.0
For Column classname Type is STRING value as String is English value as long is 0 value as double is 0.0
Information for row 2 offset=1
For Column studentid Type is STRING value as String is 00001 value as long is 1 value as double is 1.0
For Column classid Type is STRING value as String is 001 value as long is 1 value as double is 1.0
For Column pointgrade Type is INTEGER value as String is 99 value as long is 99 value as double is 99.0
For Column lettergrade Type is STRING value as String is A value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00001 value as long is 1 value as double is 1.0
For Column fname Type is STRING value as String is Fred value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Smith value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 001 value as long is 1 value as double is 1.0
For Column classname Type is STRING value as String is English value as long is 0 value as double is 0.0
Information for row 3 offset=2
For Column studentid Type is STRING value as String is 00001 value as long is 1 value as double is 1.0
For Column classid Type is STRING value as String is 101 value as long is 101 value as double is 101.0
For Column pointgrade Type is INTEGER value as String is 25 value as long is 25 value as double is 25.0
For Column lettergrade Type is STRING value as String is F value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00001 value as long is 1 value as double is 1.0
For Column fname Type is STRING value as String is Fred value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Smith value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 101 value as long is 101 value as double is 101.0
For Column classname Type is STRING value as String is Mathematics value as long is 0 value as double is 0.0
05-31 04:20:32.621 3582-3584/? D/dalvikvm: GC_CONCURRENT freed 338K, 11% free 6233K/6983K, paused 10ms+0ms, total 12ms
05-31 04:20:32.621 3582-3582/? D/SQLITE_CSU: Information for row 4 offset=3
For Column studentid Type is STRING value as String is 00001 value as long is 1 value as double is 1.0
For Column classid Type is STRING value as String is 101 value as long is 101 value as double is 101.0
For Column pointgrade Type is INTEGER value as String is 25 value as long is 25 value as double is 25.0
For Column lettergrade Type is STRING value as String is F value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00001 value as long is 1 value as double is 1.0
For Column fname Type is STRING value as String is Fred value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Smith value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 101 value as long is 101 value as double is 101.0
For Column classname Type is STRING value as String is Mathematics value as long is 0 value as double is 0.0
Information for row 5 offset=4
For Column studentid Type is STRING value as String is 00010 value as long is 8 value as double is 10.0
For Column classid Type is STRING value as String is 201 value as long is 201 value as double is 201.0
For Column pointgrade Type is INTEGER value as String is 76 value as long is 76 value as double is 76.0
For Column lettergrade Type is STRING value as String is B value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00010 value as long is 8 value as double is 10.0
For Column fname Type is STRING value as String is Mary value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Thomas value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 201 value as long is 201 value as double is 201.0
For Column classname Type is STRING value as String is Chemistry value as long is 0 value as double is 0.0
Information for row 6 offset=5
For Column studentid Type is STRING value as String is 00010 value as long is 8 value as double is 10.0
For Column classid Type is STRING value as String is 201 value as long is 201 value as double is 201.0
For Column pointgrade Type is INTEGER value as String is 76 value as long is 76 value as double is 76.0
For Column lettergrade Type is STRING value as String is B value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00010 value as long is 8 value as double is 10.0
For Column fname Type is STRING value as String is Mary value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Thomas value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 201 value as long is 201 value as double is 201.0
For Column classname Type is STRING value as String is Chemistry value as long is 0 value as double is 0.0
Information for row 7 offset=6
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column classid Type is STRING value as String is 101 value as long is 101 value as double is 101.0
For Column pointgrade Type is INTEGER value as String is 50 value as long is 50 value as double is 50.0
For Column lettergrade Type is STRING value as String is C value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column fname Type is STRING value as String is Angela value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Jones value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 101 value as long is 101 value as double is 101.0
For Column classname Type is STRING value as String is Mathematics value as long is 0 value as double is 0.0
05-31 04:20:32.637 3582-3584/? D/dalvikvm: GC_CONCURRENT freed 409K, 12% free 6226K/7047K, paused 11ms+0ms, total 13ms
05-31 04:20:32.637 3582-3582/? D/SQLITE_CSU: Information for row 8 offset=7
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column classid Type is STRING value as String is 101 value as long is 101 value as double is 101.0
For Column pointgrade Type is INTEGER value as String is 50 value as long is 50 value as double is 50.0
For Column lettergrade Type is STRING value as String is C value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column fname Type is STRING value as String is Angela value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Jones value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 101 value as long is 101 value as double is 101.0
For Column classname Type is STRING value as String is Mathematics value as long is 0 value as double is 0.0
Information for row 9 offset=8
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column classid Type is STRING value as String is 201 value as long is 201 value as double is 201.0
For Column pointgrade Type is INTEGER value as String is 63 value as long is 63 value as double is 63.0
For Column lettergrade Type is STRING value as String is C value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column fname Type is STRING value as String is Angela value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Jones value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 201 value as long is 201 value as double is 201.0
For Column classname Type is STRING value as String is Chemistry value as long is 0 value as double is 0.0
Information for row 10 offset=9
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column classid Type is STRING value as String is 201 value as long is 201 value as double is 201.0
For Column pointgrade Type is INTEGER value as String is 63 value as long is 63 value as double is 63.0
For Column lettergrade Type is STRING value as String is C value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column fname Type is STRING value as String is Angela value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Jones value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 201 value as long is 201 value as double is 201.0
For Column classname Type is STRING value as String is Chemistry value as long is 0 value as double is 0.0
Information for row 11 offset=10
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column classid Type is STRING value as String is 001 value as long is 1 value as double is 1.0
For Column pointgrade Type is INTEGER value as String is 89 value as long is 89 value as double is 89.0
For Column lettergrade Type is STRING value as String is A value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column fname Type is STRING value as String is Angela value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Jones value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 001 value as long is 1 value as double is 1.0
For Column classname Type is STRING value as String is English value as long is 0 value as double is 0.0
Information for row 12 offset=11
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column classid Type is STRING value as String is 001 value as long is 1 value as double is 1.0
For Column pointgrade Type is INTEGER value as String is 89 value as long is 89 value as double is 89.0
For Column lettergrade Type is STRING value as String is A value as long is 0 value as double is 0.0
For Column studentid Type is STRING value as String is 00910 value as long is 0 value as double is 910.0
For Column fname Type is STRING value as String is Angela value as long is 0 value as double is 0.0
For Column lname Type is STRING value as String is Jones value as long is 0 value as double is 0.0
For Column classid Type is STRING value as String is 001 value as long is 1 value as double is 1.0
For Column classname Type is STRING value as String is English value as long is 0 value as double is 0.0
额外的重复类
下面的代码扩展了上面的代码,通过添加一个新的学生来注册 001 - 英语课程(已经存在),使用:-
ContentValues cv = new ContentValues();
String studentid = "00002";
String fname = "Bert";
String lname = "Jones";
String classid = "001";
String classname = "English";
int pointgrade = 56;
String lettergrade = "C";
cv.put("studentid",studentid);
cv.put("fname",fname);
cv.put("lname",lname);
if (db.insert("STUDENT_TABLE",null,cv) > 0) {
cv.clear();
cv.put("classid",classid);
cv.put("classname",classname);
if (db.insert("CLASS_TABLE",null,cv) > 0) {
Log.d(
"CLASSADD",
"Class " +
cv.getAsString("classid") +
" - " +
cv.getAsString("classname") +
" ADDED."
);
} else {
Log.d(
"CLASSADD",
"Class " +
cv.getAsString(
"classid") +
" - " +
cv.getAsString("classname") +
" NOT ADDED (Exists)"
);
}
cv.clear();
cv.put("studentid",studentid);
cv.put("classid",classid);
cv.put("pointgrade",pointgrade);
cv.put("lettergrade",lettergrade);
if (db.insert("GRADE_TABLE",null,cv) > 0) {
Log.d("ENROLRESULT",
"Student " +
cv.getAsString("studentid") +
" - " +
cv.getAsString("fname") +
" " +
cv.getAsString("lname")
+ " pointgrade " +
String.valueOf(cv.getAsInteger("pointgrade")) +
" lettergrade " +
cv.getAsString("lettergrade") +
" ENROLLED"
);
}
}
这个:-
- 尝试添加(插入)新学生。
- 如果没有添加学生,则不会执行任何其他操作。
- 否则:-
- 尝试使用普通的
insert 方法添加(插入)已经存在的类(001 - 英语)(SQL 将是 INSERT OR IGNORE INTO CLASS_TABLE .....)。
- 日志消息表明是否添加
- 添加适当的 GRADE_TABLE 行
运行上述程序会在日志中显示以下消息:-
05-31 08:13:43.557 4476-4476/? D/CLASSADD: Class 001 - English NOT ADDED (Exists)
05-31 08:13:43.565 4476-4476/? D/ENROLRESULT: Student 00002 - null null pointgrade 56 lettergrade C ENROLLED
应用不会崩溃。
不过日志中还包括:-
05-31 08:13:43.557 4476-4476/? E/SQLiteDatabase: Error inserting classname=English classid=001
android.database.sqlite.SQLiteConstraintException: column classname is not unique (code 19)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:775)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1339)
at cpa.carpurchases.MainActivity.onCreate(MainActivity.java:99)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
- 注意没有致命的运行时异常
- 注意时间戳
- 插入@失败
- 05-31 08:13:43.557
- 但报告注册@
- 05-31 08:13:43.565
基本上,SQLite 的 insert 捕获了允许继续处理的错误,但打印了堆栈跟踪 (可以说它不应该,可以说应该)