错误:
Error 1215 (HY000): Cannot add foreign key constraint
相关 mysql 错误:Error 1215 (HY000): Cannot add foreign key constraint。
场景:
为了方便测试人员测试产品的功能以及后续报告,PM设计了一个测试用例的功能,用于记录需要测试的产品的操作步骤。针对这个功能,我建立了两个表,测试用例表TestCase
和用例步骤表TestCaseStep
。TestCase
用于记录测试用例的基本信息,TestCaseStep
记录该用例的执行步骤。
情况1:引用字段的表结构不存在
代码:
测试用例和用例步骤是一对多的关联关系,相关的 Go Gorm 模型大致如下:
type TestCase struct {
ID uint64 `gorm:"primaryKey,autoIncrement;"`
Name string `gorm:"type:varchar(200);index;default:'';not null"`
TestCaseSteps TestCaseSteps `gorm:"foreignKey:TestCaseID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" `
}
type TestCaseStep struct {
ID uint64 `gorm:"primaryKey,autoIncrement;"`
TestCaseID uint64 `gorm:"type:bigint(20) unsigned;index;not null;"`
Sequece int `gorm:"type:int(10) unsigned;""`
Detail string `gorm:"type:varchar(2000);"`
Expectation string `gorm:"type:varchar(2000);"`
}
type TestCaseSteps []*TestCaseStep
这里基本没有什么问题,主要的问题是下面这段数据库迁移的代码:
func GetEntity() []interface{} {
return []interface{}{
new(TestCaseStep),
new(TestCase),
}
}
// mysql Init:
func Init(db *gorm.DB) {
...
db.AutoMigrate(GetEntity()...)
...
}
报出错误Error 1215 (HY000)
的代码为db.AutoMigrate(GetEntity()...)
。
错误出现原因:
Gorm v2中方法AutoMigrate()
会自动迁移数据表,因此在项目初始化时,它也会自动根据我们自动定义的 orm 模型在数据库中创建对应的表结构。
上述代码db.AutoMigrate(GetEntity()...)
实际上可以这样看db.AutoMigrate(new(TestCaseStep),new(TestCase))
。它打算先创建TestCaseStep
表,再创建TestCase
表。问题就出现在这里,TestCaseStep
表和TestCase
表是多对一的关系,TestCaseStep
会将自己的字段TestCaseID
作为外键,表TestCase
的主键ID作为引用。
由于是先创建的TestCaseStep
表,所以表TestCase
此时并不存在,所以TestCaseStep
无法引用TestCase
的主键ID,于是报错:Error 1215 (HY000): Cannot add foreign key constraint。
解决:
先创建表TestCase
,再创建TestCaseStep
。
func GetEntity() []interface{} {
return []interface{}{
new(TestCase),
new(TestCaseStep),
}
}
情况2:引用字段不存在
代码:
type TestCase struct {
ID uint64 `gorm:"primaryKey,autoIncrement;"`
Name string `gorm:"type:varchar(200);index;default:'';not null"`
TestCaseSteps TestCaseSteps `gorm:"foreignKey:TestCaseID;references:TestID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" `
}
type TestCaseStep struct {
ID uint64 `gorm:"primaryKey,autoIncrement;"`
TestCaseID uint64 `gorm:"type:bigint(20) unsigned;index;not null;"`
Sequece int `gorm:"type:int(10) unsigned;`
Detail string `gorm:"type:varchar(2000);`
Expectation string `gorm:"type:varchar(2000);`
}
type TestCaseSteps []*TestCaseStep
func GetEntity() []interface{} {
return []interface{}{
new(TestCaseStep),
new(TestCase),
}
}
// mysql Init:
func Init(db *gorm.DB) {
...
db.AutoMigrate(GetEntity()...)
...
}
报出错误Error 1215 (HY000)
的代码依然为db.AutoMigrate(GetEntity()...)
。
错误出现原因:
Gorm 模型创建外键时引用表TestCase
不存在的字段TestID
:
type TestCase struct {
...
TestCaseSteps TestCaseSteps `gorm:"foreignKey:TestCaseID;references:TestID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" `
}
解决:
将references
引用的字段改为ID
。