使用双 primary/foreign 键关系创建 table 时如何修复 "java.sql.SQLException: Cannot add foreign key constraint."

How to fix "java.sql.SQLException: Cannot add foreign key constraint." when creating table with double primary/foreign key relationship

我正在使用 Kotlin 和 Jetbrain 的 Exposed SQL 库为我正在处理的项目设置数据库。我正在尝试在两个 table、cw_cache(父 table)和 cw_requests(子 table)之间建立外键关系。

此设置适用于 Sqlite 数据库,但当我尝试在 MySQL 服务器数据库中创建 table 时不起作用。我收到错误 "java.sql.SQLException: Cannot add foreign key constraint."

我已经在此处查看过类似问题,并确保父级和子级 table 中的列具有相同的数据类型,父级 table 中的列是实际上是键,并且 cw_cache table 是在 cw_requests table.

之前创建的

当我运行 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 table:

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

    // other column initializers
}

cw_request table:

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
}

根据这个问题,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 框架,所以不要问我如何使用该代码示例。如果对你有意义,祝你好运。