【问题标题】:How to fix "java.sql.SQLException: Cannot add foreign key constraint." when creating table with double primary/foreign key relationship如何修复“java.sql.SQLException:无法添加外键约束”。创建具有双主/外键关系的表时
【发布时间】:2019-04-05 23:03:17
【问题描述】:

我正在为我正在使用 Kotlin 和 Jetbrain 的 Exposed SQL 库开展的项目设置数据库。我正在尝试在 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
}

【问题讨论】:

  • 您需要在子表上创建一个复合外键,而不是两个外键,该外键引用父表的两个主键列。跨度>

标签: mysql sql kotlin foreign-keys kotlin-exposed


【解决方案1】:

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

【讨论】:

  • 谢谢,我想我应该先看看他们的github。我已经实施了该解决方法的一个版本,可以解决我的问题。
猜你喜欢
  • 2021-02-19
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
  • 2016-03-27
  • 2020-02-09
  • 2019-01-31
  • 2021-10-16
  • 2017-12-05
相关资源
最近更新 更多