Как исправить «java.sql.SQLException: невозможно добавить ограничение внешнего ключа». при создании таблицы с двойным отношением первичный / внешний ключ - PullRequest
2 голосов
/ 06 апреля 2019

Я устанавливаю базу данных для проекта, над которым я работаю, используя библиотеку Exposed SQL от Kotlin и Jetbrain.и я пытаюсь установить отношение внешнего ключа между двумя таблицами, cw_cache (родительская таблица) и cw_requests (дочерняя таблица).

Эта установка прекрасно работает с базой данных Sqlite, но не работает, когда я пытаюсь создатьтаблицы в базе данных сервера MySQL.Я получаю сообщение об ошибке «java.sql.SQLException: не удается добавить ограничение внешнего ключа».

Я уже рассмотрел подобные проблемы здесь и убедился, что столбцы в родительской и дочерней таблицах имеют одинаковые данныевведите, что столбцы в родительской таблице на самом деле являются ключами и что таблица cw_cache создается перед таблицей cw_requests.

Когда я запускаю SHOW ENGINE INNODB STATUS;, чтобы увидеть ошибку внешнего ключа, я вижу это:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
2019-04-05 18:29:17 2e94 Error in foreign key constraint of table coursewatcher/cw_requests:
FOREIGN KEY (term) REFERENCES cw_cache(term) ON DELETE RESTRICT ON UPDATE RESTRICT):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html
for correct foreign key definition.

Диаграмма из базы данных Sqlite: https://gyazo.com/220dd4b1a3d301419e0b8b73bfc80a68

Соответствующий код:

Таблица cw_cache:

object Cache : Table("cw_cache") {
    val crn = varchar("crn", 5).primaryKey()
    val term = varchar("term", 6).primaryKey()

    // other column initializers
}

Таблица cw_request:

object Requests : Table("cw_requests") {
    val id = long("id").primaryKey()
    val orderId = long("order_id") references Orders.id
    val crn = varchar("crn", 5) references Cache.crn
    val term = varchar("term", 6) references Cache.term

    // other column initializers
}

1 Ответ

2 голосов
/ 06 апреля 2019

Объявление составных внешних ключей в настоящее время не реализовано в структуре Exposed, согласно этому вопросу: https://github.com/JetBrains/Exposed/issues/511

В ответе на этот вопрос приведен пример кода для обхода проблемы вручную:

val t = TransactionManager.current()
val fk = ForeignKeyConstraint("fk_name",
                    t.identity(TableA), "{t.identity(TableA.idA)}, {t.identity(TableA.idA)}",
                    t.identity(TableB), "{t.identity(TableB.idA)}, {t.identity(TableB.idA)}",
                    ReferenceOption.RESTRICT,
                    ReferenceOption.RESTRICT)
t.exec(fk.createStatement().firsts())

Я не использовал Kotlin или Exposed framework, поэтому не спрашивайте меня, как использовать этот пример кода. Если это имеет смысл для вас, удачи вам.

...