なにこれ
筆者がgolangとgormで遊んでる時に、数時間も↓のエラーに悩まされたため、備忘録として残します。
Error 3780: Referencing column 'book_id' and referenced column 'id' in foreign key constraint 'book_details_book_id_books_id_foreign' are incompatible.
結論
従属テーブルの型をuint
型に変更すると解消する。
経緯
下記のBook
テーブル(親)とBookDetail
テーブル(子 or 従属)がありました。
type Book struct {
gorm.Model
BookDetail BookDetail
}
type BookDetail struct {
gorm.Model
BookID int
}
↑の状態で、gormのAddForeignKey
をやるとエラーを吐きます
func Migrate() {
db.AutoMigrate(&model.Book{})
db.CreateTable(&model.BookDetail{})
db.Model(&model.BookDetail{}).AddForeignKey("book_id", "books(id)", "CASCADE", "CASCADE")
}
↓結果
Error 3780: Referencing column 'book_id' and referenced column 'id' in foreign key constraint 'book_details_book_id_books_id_foreign' are incompatible.
訳)エラー3780:外部キー制約「book_details_book_id_books_id_foreign」の参照列「book_id」と参照列「id」に互換性がありません。
簡単にまとめると、mysqlでIDの型が一致しない場合に起きるエラーです。
試したこと
BookDetail struct
のBookID
の型をint
型からuint
型に変更しました。
type BookDetail struct {
gorm.Model
// BookID int
BookID uint
}
理由
Books
テーブルのID
の型は、↓の画像の通りint unsigned
になってるから。
そちらに合わせてあげれば、型が一致するので解決します。
余談
unsigned
とは
整数型は正の数と負の数を扱うことができますが、データ型の後に UNSIGNED を付けると 0 と正の数しか格納できなくなります。このようなデータ型を符号なし整数型といいます。
参考:整数型(TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT)
gormがuint型でIDを作成するから、それに合わせる必要があるって感じでした。
感想
Goを触り始めて2週間ほどですが、
以外にもMySQLのエラーでハマるとは思ってませんでした!
まだまだ知らないことがたくさんありました。