Так что, в принципе, если все три таблицы должны быть названы _id, какой синтаксис я
предполагается использовать при создании внешних ключей, если внешние ключи имеют
то же имя, что и первичный ключ ссылочной таблицы, поэтому я буду
всегда получаю ошибку создания дубликатов столбцов.
Они не должны быть такими, как вы могли бы использовать AS _id для динамического создания столбца с псевдонимом (обратите внимание, что * у вас есть id , а также _id столбец) например
SELECT *, id AS _id
- вам может понадобиться только 1 _id столбец для CursorAdapter.
Что касается определения внешнего ключа с использованием
INTEGER PRIMARY KEY _id,....., FOREIGN KEY(_id) REFERENCES parent_table(column_in_parent_table)
это, вероятно, НЕ будет работать последовательно / хорошо / с пользой.
Вы фактически говорите, что столбец _id должен быть значением в родительской таблице. Таким образом, вы ограничиваете отношение 1-1, поскольку INTEGER PRIMARY KEY
неявно уникально, так как это псевдоним обычно скрытого столбца rowid , значение, поскольку столбец является специальным, ДОЛЖЕН также быть целым числом .
например. если первая строка таблицы курсов ссылается на столбец со значением 1, то отлично (скажем, TERM1), тогда в этой таблице не может быть другой ссылки на TERM1, поскольку _id НЕ ДОЛЖЕН быть 1.
- Таким образом, уникальное ограничение (дубликаты), с которым вы столкнулись.
Короче говоря, вы должны ссылаться на столбец _id в качестве столбца родительской таблицы внешнего ключа (в вашем случае), но не использовать столбец _id в дочерней таблице в качестве столбец, который ссылается на родительскую таблицу, поскольку вы ограничиваете родительский элемент только одним дочерним элементом для этого значения, отношение 1-1 (что фактически означает, что две таблицы являются избыточными).
Вместо этого столбец в дочерней таблице должен быть столбцом, предназначенным главным образом для хранения ссылки / отношения / ассоциации (это может быть значение, которое используется в других целях).
Как таковой вы хотите что-то вроде: -
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TERM_TABLE_NAME + " (_id INTEGER PRIMARY KEY, termName TEXT, termStart TEXT, termEnd TEXT)");
db.execSQL("CREATE TABLE " + COURSES_TABLE_NAME + " (_id INTEGER PRIMARY KEY, courseTitle TEXT, courseStartDate TEXT, courseEndDate TEXT, courseStatus INTEGER, optionalNote TEXT, mentorName TEXT, mentorPhone TEXT, mentorEmail TEXT, course_term_reference INTEGER REFERENCES term_table(_id))");
db.execSQL("CREATE TABLE " + ASSESS_TABLE_NAME + " (_id INTEGER PRIMARY KEY, assessName TEXT, assessDueDate TEXT, assessType INTEGER, assess_course_reference INTEGER REFERENCES courses_table(_id))");
}
- Примечание AUTOINCREMENT был удален, вам не нужно ни это, ни накладные расходы, которые он несет SQLite Autoincrement согласно: -
- Ключевое слово AUTOINCREMENT накладывает дополнительный процессор, память, дисковое пространство и
издержки дискового ввода-вывода, и их следует избегать, если в этом нет особой необходимости. это
обычно не требуется.
- Были использованы более простые и, возможно, более понятные определения внешнего ключа столбца (т.е. внешние ключи были определены на уровне определения столбца, а не на уровне определения таблицы)
Однако я бы рекомендовал кодировать идентификаторы (имена столбцов, имена таблиц и т. Д.) Один раз как константы, а затем всегда ссылаться на эти константы.
Как таковой, я бы предложил, что выше было бы лучше, как: -
public static final String TERM_TABLE_NAME = "term_table";
public static final String COL_TERM1 = "_id";
public static final String COL_TERM2 = "termName";
public static final String COL_TERM3 = "termStart";
public static final String COL_TERM4 = "termEnd";
public static final String TERM_DATABASE_NAME = "term.db";
public static final int DBVERSION = 1;
//courses table
public static final String COURSES_TABLE_NAME = "courses_table";
public static final String COL_COURSE1 = "_id";
public static final String COL_COURSE2 = "courseTitle";
public static final String COL_COURSE3 = "courseStartDate";
public static final String COL_COURSE4 = "courseEndDate";
public static final String COL_COURSE5 = "courseStatus";
public static final String COL_COURSE6 = "optionalNote";
public static final String COL_COURSE7 = "mentorName";
public static final String COL_COURSE8 = "mentorPhone";
public static final String COL_COURSE9 = "mentorEmail";
public static final String COL_COURSE_TERM_REFERENCE = "term_reference";
//assess table
public static final String ASSESS_TABLE_NAME = "assess_table";
public static final String COL_ASSESS1 = "_id";
public static final String COL_ASSESS2 = "assessName";
public static final String COL_ASSESS3 = "assessDueDate";
public static final String COL_ASSESS4 = "assessType";
public static final String COL_ASSESS_COURSE_REFERENCE = "course_reference";
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(
"CREATE TABLE " + TERM_TABLE_NAME + "(" +
COL_TERM1 + " INTEGER PRIMARY KEY," +
COL_TERM2 + " TEXT, " +
COL_TERM3 + " TEXT, " +
COL_TERM4 + " TEXT" +
")"
);
db.execSQL(
"CREATE TABLE " + COURSES_TABLE_NAME + "(" +
COL_COURSE1 + " INTEGER PRIMARY KEY, " +
COL_COURSE2 + " TEXT, " +
COL_COURSE3 + " TEXT, " +
COL_COURSE4 + " TEXT, " +
COL_COURSE5 + " INTEGER, " +
COL_COURSE6 + " TEXT, " +
COL_COURSE7 + " TEXT, " +
COL_COURSE8 + " TEXT, " +
COL_COURSE9 + " TEXT, " +
COL_COURSE_TERM_REFERENCE + "INTEGER REFERENCES " + TERM_TABLE_NAME + "(" + COL_TERM1 + ")" +
")"
);
db.execSQL(
"CREATE TABLE " + ASSESS_TABLE_NAME + "(" +
COL_ASSESS1 + " INTEGER PRIMARY KEY, " +
COL_ASSESS2 + " TEXT, " +
COL_ASSESS3 + " TEXT, " +
COL_ASSESS4 + " INTEGER, " +
COL_ASSESS_COURSE_REFERENCE + " INTEGER REFERENCES " + COURSES_TABLE_NAME + "(" + COL_COURSE1 + ")" +
")"
);
}
Приведенный выше результат в SQL (для каждой таблицы) выглядит так: -
CREATE TABLE term_table(_id INTEGER PRIMARY KEY,termName TEXT, termStart TEXT, termEnd TEXT)
CREATE TABLE courses_table(courses_id INTEGER PRIMARY KEY, courseTitle TEXT, courseStartDate TEXT, courseEndDate TEXT, courseStatus INTEGER, optionalNote TEXT, mentorName TEXT, mentorPhone TEXT, mentorEmail TEXT, term_reference INTEGER REFERENCES term_table(_id))
CREATE TABLE assess_table(assess_id INTEGER PRIMARY KEY, assessName TEXT, assessDueDate TEXT, assessType INTEGER, course_reference INTEGER REFERENCES courses_table(courses_id))
Дополнительный
Чтобы использовать поддержку внешнего ключа, его необходимо включить. Таким образом, вы можете переопределить метод onConfigure помощника базы данных, чтобы включить поддержку, например. : -
@Override
public void onConfigure(SQLiteDatabase db) {
super.onConfigure(db);
db.setForeignKeyConstraintsEnabled(true);
}