Одним из способов может быть включение внешнего ключа (не то, что вам нужно будет включать обработку внешнего ключа, так как он выключен по умолчанию).
В основном внешний ключ вводитограничение, которое говорит, что дочерний элемент может быть добавлен, только если значение, применяемое к дочернему элементу, существует в родительском элементе.
Дочерний и родительский элемент представляют собой комбинацию таблицы / столбца (или столбцов).
Поскольку вы говорите, что значение в таблице user_info должно существовать в таблице user_reg, то user_reg будет родительским, а user_info - дочерним в столбце, имя которого равно studentid.
Таким образом, вы можете определить внешний ключиспользуя: -
CREATE TABLE IF NOT EXISTS user_info (studentid INTEGER PRIMARY KEY REFERENCES user_reg(studentid), email TEXT, password TEXT);
- Обратите внимание, предполагается, что у студента будет только один студент
Однако, поскольку внешний ключ должен указывать на уникальную строкув родителе это ограничит таблицу user_reg наличием только 1 записи на каждого учащегося, что, вероятно, нежелательно.
Это подчеркивает основную проблему, вы в основномЕсли вы смотрите на схему / структуру не так, чтобы вы могли сосредоточиться на рассмотрении структуры с точки зрения курса.
Предполагается, что отдельные аспекты пользователя, его имя,их идентификатор, адрес электронной почты и т. д. принадлежат таблице user_info, в которой имеется по одной строке на каждого учащегося, и что таблица user_reg (регистрация в курсе) должна рассматриваться как курс или курсы, в которых зарегистрирован учащийся, и как таковой, что один студентможет быть зарегистрировано много раз (в отдельных курсах), и, таким образом, это должен быть ребенок, а user_info должен быть родителем.
Возможно, вам следует использовать: -
CREATE TABLE IF NOT EXISTS user_info (studentid INTEGER PRIMARY KEY, email TEXT, password TEXT, username TEXT);
CREATE TABLE IF NOT EXISTS user_reg (studentid INTEGER REFERENCES user_info, course TEXT);
Затем вы сначала добавите студента в таблицу user_info, а затем добавите студента в курс / курсы, например: -
INSERT INTO user_info VALUES
(1,'Fred@email.mail','fredismypassword','UserFred'),
(2,'Mary@email.mail','maryismypassword','UserMary'),
(3,'Sue@email.mail','sureismypassword','UserSue')
;
INSERT INTO user_reg VALUES
(1,'English'),(1,'Woodwork'),(1,'Chemistry'),
(2,'Geography'),
(3,'Chemistry')
;
- Таким образом, Фред зарегистрирован на 3 курса, Мэри и Сьюпо одному на каждый
Например, запрос может быть: -
SELECT * FROM user_reg JOIN user_info ON user_reg.studentid = user_info.studentid ORDER BY course;
Это приведет к: -
![enter image description here](https://i.stack.imgur.com/qG6Ts.png)
Попытка добавить несуществующего студента, например, с помощью: -
INSERT INTO user_reg VALUES (10,'English') -- Oooops no such student ID
Результатом будет
INSERT INTO user_reg VALUES (10,'English') -- Oooops no such student ID
> FOREIGN KEY constraint failed
ПримерИспользуя Android
Собрав все вместе (повторяя вышеупомянутое на Android), вы получите код:
StudentDBHelper.java (Помощник по базам данных)
public class StudentDBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "studentdb";
public static final int DBVERSION = 1;
public static final String TBl_USERINFO = "user_info";
public static final String TBL_USERREG = "user_reg";
public static final String COL_USERINFO_STUDENTID = "student_id";
public static final String COL_USERINFO_USERNAME = "username";
public static final String COL_USERINFO_EMAIL = "email";
public static final String COL_USERINFO_PASSWORD = "password";
public static final String COL_USERREG_STUDENT_ID = "student_id";
public static final String COL_USERREG_COURSE = "course";
private final String crtUserInfo = "CREATE TABLE IF NOT EXISTS " + TBl_USERINFO + "(" +
COL_USERINFO_STUDENTID + " INTEGER PRIMARY KEY, " +
COL_USERINFO_USERNAME + " TEXT, " +
COL_USERINFO_EMAIL + " TEXT," +
COL_USERINFO_PASSWORD + " TEXT" +
")";
private final String drpUerInfo = "DROP TABLE IF EXISTS " + TBl_USERINFO;
private final String crtUserReg = "CREATE TABLE IF NOT EXISTS " + TBL_USERREG + "(" +
COL_USERREG_STUDENT_ID + " INTEGER REFERENCES " + TBl_USERINFO + "(" + COL_USERINFO_STUDENTID + ")," +
COL_USERREG_COURSE + " TEXT " +
")";
private final String drpUserReg = " DROP TABLE If EXISTS " + TBL_USERREG;
SQLiteDatabase mDB;
public StudentDBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase(); //<<<<<<<<<< will force create when constructing if DB doesn't exist
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(crtUserInfo);
db.execSQL(crtUserReg);
}
@Override
public void onConfigure(SQLiteDatabase db) {
super.onConfigure(db);
db.setForeignKeyConstraintsEnabled(true); //<<<<<<<<<< TURN ON FOREIGN KEY HANDLING
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(drpUserReg); //<<<<<<<<<< must be done before UserInfo
db.execSQL(drpUerInfo);
}
public long addUserInfo(String userName, String email, String password) {
ContentValues cv = new ContentValues();
cv.put(COL_USERINFO_USERNAME,userName);
cv.put(COL_USERINFO_EMAIL,email);
cv.put(COL_USERINFO_PASSWORD,password);
return mDB.insert(TBl_USERINFO,null,cv);
}
public long addUserReg(long studentId, String course) {
ContentValues cv = new ContentValues();
cv.put(COL_USERREG_STUDENT_ID,studentId);
cv.put(COL_USERREG_COURSE,course);
return mDB.insert(TBL_USERREG,null,cv);
}
public void logStudentsInCourses() {
String tbl = TBL_USERREG +
" JOIN " + TBl_USERINFO + " ON " +
TBl_USERINFO + "." + COL_USERINFO_STUDENTID +
" = " +
TBL_USERREG + "." + COL_USERREG_STUDENT_ID;
Cursor csr = mDB.query(tbl,null,null,null,null,null,COL_USERREG_COURSE);
while (csr.moveToNext()) {
Log.d(
"DBINFO",
"Row " + String.valueOf(csr.getPosition() + 1) +
"\n\t Student UserName = " + csr.getString(csr.getColumnIndex(COL_USERINFO_USERNAME)) +
"\n\tStudent Email = " + csr.getString(csr.getColumnIndex(COL_USERINFO_EMAIL)) +
"\n\tStudent password = " + csr.getString(csr.getColumnIndex(COL_USERINFO_PASSWORD)) +
"\n\tEnrolled in Course " + csr.getString(csr.getColumnIndex(COL_USERREG_COURSE))
);
}
}
}
##MainActivity.java (вызывающее действие)
public class MainActivity extends AppCompatActivity {
StudentDBHelper mDBHlpr;
Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
mDBHlpr = new StudentDBHelper(this);
mDBHlpr.addUserInfo("Fred","fred@email.com","fredpassword"); //<<<<<<<<<< will return 1 as this will be the generated value (first run only)
mDBHlpr.addUserInfo("Mary","mary@email.com","marypassword");
mDBHlpr.addUserInfo("Sue","sue@email.com","suepassword");
mDBHlpr.addUserReg(1,"English");
mDBHlpr.addUserReg(1,"Wooodwork");
mDBHlpr.addUserReg(1,"Chemistry");
mDBHlpr.addUserReg(2,"Geography");
mDBHlpr.addUserReg(3,"Chemistry");
mDBHlpr.addUserReg(10,"Chemistry"); //<<<<<<<<< Ooops won't insert return will be -1
mDBHlpr.logStudentsInCourses();
}
}
- Обратите внимание, что приведенное выше предназначено для запуска только один раз
Результат
Выше, когдапри первом запуске выдает следующее в журнал: -
2019-02-03 13:57:09.829 15640-15640/so.cdfa E/SQLiteDatabase: Error inserting student_id=10 course=Chemistry
android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:796)
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:1564)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1433)
at so.cdfa.StudentDBHelper.addUserReg(StudentDBHelper.java:80)
at so.cdfa.MainActivity.onCreate(MainActivity.java:37)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 1
Student UserName = Fred
Student Email = fred@email.com
Student password = fredpassword
Enrolled in Course Chemistry
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 2
Student UserName = Sue
Student Email = sue@email.com
Student password = suepassword
Enrolled in Course Chemistry
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 3
Student UserName = Fred
Student Email = fred@email.com
Student password = fredpassword
Enrolled in Course English
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 4
Student UserName = Mary
Student Email = mary@email.com
Student password = marypassword
Enrolled in Course Geography
2019-02-03 13:57:09.831 15640-15640/so.cdfa D/DBINFO: Row 5
Student UserName = Fred
Student Email = fred@email.com
Student password = fredpassword
Enrolled in Course Wooodwork
- Обратите внимание, что исключение не является временем выполнения / фатальным исключением и не останавливает обработку, оно просто сообщает об ошибке вставкииз-за конфликта внешнего ключа.