Как добавить внешний ключ в таблицу в SQLite?

Я создал две таблицы под названием TermTable и CourseTable. Я хочу, чтобы у CourseTable был внешний ключ для ссылки на TermTable.

Это код, в котором я создаю таблицы:


public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table " + TermDbSchema.TermTable.NAME + "(" +
                "_id integer primary key autoincrement, " +
                TermDbSchema.TermTable.Cols.UUID + ", " +
                TermDbSchema.TermTable.Cols.TITLE + ", " +
                TermDbSchema.TermTable.Cols.START_DATE + ", " +
                TermDbSchema.TermTable.Cols.END_DATE +
                ")"
        );
//I want to give CourseTable a foreign key to reference TermTable^^
        db.execSQL("create table " + TermDbSchema.CourseTable.NAME + "(" +
                "_id integer primary key autoincrement, " +
                TermDbSchema.CourseTable.Cols.UUID + ", " +
                TermDbSchema.CourseTable.Cols.TITLE + ", " +
                TermDbSchema.CourseTable.Cols.START_DATE + ", " +
                TermDbSchema.CourseTable.Cols.END_DATE + ", " +
                TermDbSchema.CourseTable.Cols.COURSE_STATUS + ", " +
                TermDbSchema.CourseTable.Cols.OPTIONAL_NOTE + ", " +
                TermDbSchema.CourseTable.Cols.MENTOR_NAME + ", " +
                TermDbSchema.CourseTable.Cols.MENTOR_PHONE + ", " +
                TermDbSchema.CourseTable.Cols.MENTOR_EMAIL +

                ")"
        );
}

Это код схемы кода:

public class TermDbSchema {

public static final class TermTable {
        public static final String NAME = "terms";
        public static final class Cols {
            public static final String UUID = "uuid";
            public static final String TITLE = "title";
            public static final String START_DATE = "startdate";
            public static final String END_DATE = "enddate";
        }
    }
    public static final class CourseTable {
        public static final String NAME = "courses";
        public static final class Cols {
            public static final String UUID = "uuid";
            public static final String TITLE = "title";
            public static final String START_DATE = "startdate";
            public static final String END_DATE = "enddate";
            public static final String COURSE_STATUS = "coursestatus";
            public static final String OPTIONAL_NOTE = "optionalnote";
            public static final String MENTOR_NAME = "mentorname";
            public static final String MENTOR_PHONE = "mentorphone";
            public static final String MENTOR_EMAIL = "mentoremail";        
        }
}

Как добавить внешний ключ в CourseTable, чтобы он мог ссылаться на TermTable?

Посмотрите синтаксис CREATE TABLE, в том числе, как пометить столбцы как внешние ключи, здесь: sqlite.org/lang_createtable.html

Shawn 02.05.2019 23:18

Также описано с примерами здесь: sqlite.org/foreignkeys.html

Shawn 02.05.2019 23:20
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
100
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Определите строку внутри класса Cols класса CourseTable, которая будет содержать имя этого нового столбца, например:

public static final String TERM_ID = "term_id";

Измените CREATE оператор таблицы CourseTable:

db.execSQL("create table " + TermDbSchema.CourseTable.NAME + "(" +
        "_id integer primary key autoincrement, " +
        TermDbSchema.CourseTable.Cols.UUID + ", " +
        TermDbSchema.CourseTable.Cols.TITLE + ", " +
        TermDbSchema.CourseTable.Cols.START_DATE + ", " +
        TermDbSchema.CourseTable.Cols.END_DATE + ", " +
        TermDbSchema.CourseTable.Cols.COURSE_STATUS + ", " +
        TermDbSchema.CourseTable.Cols.OPTIONAL_NOTE + ", " +
        TermDbSchema.CourseTable.Cols.MENTOR_NAME + ", " +
        TermDbSchema.CourseTable.Cols.MENTOR_PHONE + ", " +
        TermDbSchema.CourseTable.Cols.MENTOR_EMAIL + ", " +
        TermDbSchema.CourseTable.Cols.TERM_ID + " INTEGER, " +
        "FOREIGN KEY (" + TermDbSchema.CourseTable.Cols.TERM_ID +
        ") REFERENCES " + TermDbSchema.TermTable.NAME + "(_id)" + 
        ")"
);

Этот новый столбец будет ссылаться на столбец _id, который является ПЕРВИЧНЫМ КЛЮЧЕМ TermTable.
Вам нужно удалить приложение с устройства, чтобы база данных была удалена, а затем повторно запустить, чтобы воссоздать базу данных.

это нехорошо setForeignKeyConstraintsEnabled(true) для открытия базы данных или onConfigure, в противном случае ничего не происходит.

user10937486 03.05.2019 05:49
Ответ принят как подходящий

Измените CourseTable, чтобы иметь другой столбец для ссылки (ссылка, отношение, ассоциация, сопоставление — все остальные термины): -

public static final class CourseTable {
    public static final String NAME = "courses";
    public static final class Cols {
        public static final String UUID = "uuid";
        public static final String TITLE = "title";
        public static final String START_DATE = "startdate";
        public static final String END_DATE = "enddate";
        public static final String COURSE_STATUS = "coursestatus";
        public static final String OPTIONAL_NOTE = "optionalnote";
        public static final String MENTOR_NAME = "mentorname";
        public static final String MENTOR_PHONE = "mentorphone";
        public static final String MENTOR_EMAIL = "mentoremail"; 
        public static final String TERM_LINK = "termlink"    //<<<<<<<<<< ADDED   
    }
  • имя столбца, конечно, может быть тем, что вы хотите

Измените таблицу Создание SQL для курсов, чтобы добавить ограничение внешнего ключа.

         db.execSQL("create table " + TermDbSchema.CourseTable.NAME + "(" +
            "_id integer primary key autoincrement, " +
            TermDbSchema.CourseTable.Cols.UUID + ", " +
            TermDbSchema.CourseTable.Cols.TITLE + ", " +
            TermDbSchema.CourseTable.Cols.START_DATE + ", " +
            TermDbSchema.CourseTable.Cols.END_DATE + ", " +
            TermDbSchema.CourseTable.Cols.COURSE_STATUS + ", " +
            TermDbSchema.CourseTable.Cols.OPTIONAL_NOTE + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_NAME + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_PHONE + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_EMAIL + ", " + //<<<<<<<<<< CHANGED
            TermDbSchema.CourseTable.Cols.TERM_LINK + " INTEGER REFERENCES " + TermDbSchema.TermTable.NAME + "(_id)" + //<<<<<<<<<< ADDED

            ")"
    );
  • вы можете придерживаться своих соглашений, опуская INTEGER (сходство типа столбца), это не будет проблемой. Он был включен, потому что большинство из них указали бы типы столбцов, а не применяли значения по умолчанию (ЧИСЛОВЫЕ).

Важный

Затем переопределите onConfigure, чтобы вызвать передачу setForeignKeyConstraintsEnabled true.

например :-

@Override
public void onConfigure(SQLiteDatabase db) {
    super.onConfigure(db);
    db.setForeignKeyConstraintsEnabled(true);
}
  • По умолчанию поддержка внешнего ключа отключена, внесение вышеуказанных изменений в кодировку будет бесполезным, если поддержка внешнего ключа не включена.

Затем вам нужно будет сделать 1 из следующего: -

  • Удалить данные приложения
  • Удалить приложение

а затем перезапустите приложение.

  • Примечание любые существующие данные будут потеряны. Если вам нужно сохранить данные, это может быть относительно сложно.

Внешние ключи

Обратите внимание, что определение внешнего ключа ТОЛЬКО определяет ограничение (правило), которое требует, чтобы значение помещалось в столбец, который имеет ограничение, чтобы быть значением в одной из строк родительской таблицы/столбца, на который ссылаются.

Определение ограничения внешнего ключа НЕ ОБЕСПЕЧИВАЕТ автоматические установление отношений. То есть вам все равно придется определять соответствующий термин при добавлении курса (распространенное заблуждение состоит в том, что он это делает).

Возможно, вы захотите расширить определение, включив в него действия ON DELETE и ON UPDATE, такие как CASCADE. например ON DELETE CASCADE при удалении строки термина (если) удаляет дочерние строки в таблице курса. Точно так же ON UPDATE CASCADE обновит ссылочное значение дочерних элементов в таблице курсов, если это значение будет изменено в таблице терминов (это может упростить жизнь).

например вы можете использовать: -

    TermDbSchema.CourseTable.Cols.TERM_LINK + " INTEGER REFERENCES " + TermDbSchema.TermTable.NAME + "(_id) ON DELETE CASCADE ON UPDATE CASCADE" + //<<<<<<<<<< ADDED

Вы можете обратиться к Поддержка внешнего ключа SQLite

Другие вопросы по теме