マイグレーション

自動マイグレーション

スキーマを自動的に移行し、スキーマを最新の状態に保ちます。

注意: AutoMigrate は、テーブル、不足している外部キー、制約、列、インデックスを作成します。既存の列の型がサイズ、精度、null 許容に変更された場合、それを変更します。データを保護するために、未使用の列は削除しません

db.AutoMigrate(&User{})

db.AutoMigrate(&User{}, &Product{}, &Order{})

// Add table suffix when creating tables
db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})

注意 AutoMigrate はデータベースの外部キー制約を自動的に作成します。初期化中にこの機能を無効にできます。例えば

db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
})

Migrator インターフェース

GORM は、データベースに依存しないマイグレーションを構築するために使用できる、各データベースの統一された API インターフェースを含む migrator インターフェースを提供します。例えば

SQLite は ALTER COLUMNDROP COLUMN をサポートしていません。GORM は変更しようとしているテーブルと同じ新しいテーブルを作成し、すべてのデータをコピーし、古いテーブルを削除し、新しいテーブルの名前を変更します。

MySQL は一部のバージョンで列名やインデックスの変更をサポートしていません。GORM は使用している MySQL のバージョンに基づいて異なる SQL を実行します。

type Migrator interface {
// AutoMigrate
AutoMigrate(dst ...interface{}) error

// Database
CurrentDatabase() string
FullDataTypeOf(*schema.Field) clause.Expr

// Tables
CreateTable(dst ...interface{}) error
DropTable(dst ...interface{}) error
HasTable(dst interface{}) bool
RenameTable(oldName, newName interface{}) error
GetTables() (tableList []string, err error)

// Columns
AddColumn(dst interface{}, field string) error
DropColumn(dst interface{}, field string) error
AlterColumn(dst interface{}, field string) error
MigrateColumn(dst interface{}, field *schema.Field, columnType ColumnType) error
HasColumn(dst interface{}, field string) bool
RenameColumn(dst interface{}, oldName, field string) error
ColumnTypes(dst interface{}) ([]ColumnType, error)

// Views
CreateView(name string, option ViewOption) error
DropView(name string) error

// Constraints
CreateConstraint(dst interface{}, name string) error
DropConstraint(dst interface{}, name string) error
HasConstraint(dst interface{}, name string) bool

// Indexes
CreateIndex(dst interface{}, name string) error
DropIndex(dst interface{}, name string) error
HasIndex(dst interface{}, name string) bool
RenameIndex(dst interface{}, oldName, newName string) error
}

CurrentDatabase

現在使用中のデータベース名を返します。

db.Migrator().CurrentDatabase()

テーブル

// Create table for `User`
db.Migrator().CreateTable(&User{})

// Append "ENGINE=InnoDB" to the creating table SQL for `User`
db.Set("gorm:table_options", "ENGINE=InnoDB").Migrator().CreateTable(&User{})

// Check table for `User` exists or not
db.Migrator().HasTable(&User{})
db.Migrator().HasTable("users")

// Drop table if exists (will ignore or delete foreign key constraints when dropping)
db.Migrator().DropTable(&User{})
db.Migrator().DropTable("users")

// Rename old table to new table
db.Migrator().RenameTable(&User{}, &UserInfo{})
db.Migrator().RenameTable("users", "user_infos")

type User struct {
Name string
}

// Add name field
db.Migrator().AddColumn(&User{}, "Name")
// Drop name field
db.Migrator().DropColumn(&User{}, "Name")
// Alter name field
db.Migrator().AlterColumn(&User{}, "Name")
// Check column exists
db.Migrator().HasColumn(&User{}, "Name")

type User struct {
Name string
NewName string
}

// Rename column to new name
db.Migrator().RenameColumn(&User{}, "Name", "NewName")
db.Migrator().RenameColumn(&User{}, "name", "new_name")

// ColumnTypes
db.Migrator().ColumnTypes(&User{}) ([]gorm.ColumnType, error)

type ColumnType interface {
Name() string
DatabaseTypeName() string // varchar
ColumnType() (columnType string, ok bool) // varchar(64)
PrimaryKey() (isPrimaryKey bool, ok bool)
AutoIncrement() (isAutoIncrement bool, ok bool)
Length() (length int64, ok bool)
DecimalSize() (precision int64, scale int64, ok bool)
Nullable() (nullable bool, ok bool)
Unique() (unique bool, ok bool)
ScanType() reflect.Type
Comment() (value string, ok bool)
DefaultValue() (value string, ok bool)
}

ビュー

ViewOption でビューを作成します。ViewOption について

  • Queryサブクエリであり、必須です。
  • Replace が true の場合、CREATE OR REPLACE を実行し、それ以外の場合は CREATE を実行します。
  • CheckOption が空でない場合、SQL に追加します。例えば WITH LOCAL CHECK OPTION

注意 SQLite は現在、ViewOption での Replace をサポートしていません。

query := db.Model(&User{}).Where("age > ?", 20)

// Create View
db.Migrator().CreateView("users_pets", gorm.ViewOption{Query: query})
// CREATE VIEW `users_view` AS SELECT * FROM `users` WHERE age > 20

// Create or Replace View
db.Migrator().CreateView("users_pets", gorm.ViewOption{Query: query, Replace: true})
// CREATE OR REPLACE VIEW `users_pets` AS SELECT * FROM `users` WHERE age > 20

// Create View With Check Option
db.Migrator().CreateView("users_pets", gorm.ViewOption{Query: query, CheckOption: "WITH CHECK OPTION"})
// CREATE VIEW `users_pets` AS SELECT * FROM `users` WHERE age > 20 WITH CHECK OPTION

// Drop View
db.Migrator().DropView("users_pets")
// DROP VIEW IF EXISTS "users_pets"

制約

type UserIndex struct {
Name string `gorm:"check:name_checker,name <> 'jinzhu'"`
}

// Create constraint
db.Migrator().CreateConstraint(&User{}, "name_checker")

// Drop constraint
db.Migrator().DropConstraint(&User{}, "name_checker")

// Check constraint exists
db.Migrator().HasConstraint(&User{}, "name_checker")

リレーションシップの外部キーを作成します。

type User struct {
gorm.Model
CreditCards []CreditCard
}

type CreditCard struct {
gorm.Model
Number string
UserID uint
}

// create database foreign key for user & credit_cards
db.Migrator().CreateConstraint(&User{}, "CreditCards")
db.Migrator().CreateConstraint(&User{}, "fk_users_credit_cards")
// ALTER TABLE `credit_cards` ADD CONSTRAINT `fk_users_credit_cards` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)

// check database foreign key for user & credit_cards exists or not
db.Migrator().HasConstraint(&User{}, "CreditCards")
db.Migrator().HasConstraint(&User{}, "fk_users_credit_cards")

// drop database foreign key for user & credit_cards
db.Migrator().DropConstraint(&User{}, "CreditCards")
db.Migrator().DropConstraint(&User{}, "fk_users_credit_cards")

インデックス

type User struct {
gorm.Model
Name string `gorm:"size:255;index:idx_name,unique"`
}

// Create index for Name field
db.Migrator().CreateIndex(&User{}, "Name")
db.Migrator().CreateIndex(&User{}, "idx_name")

// Drop index for Name field
db.Migrator().DropIndex(&User{}, "Name")
db.Migrator().DropIndex(&User{}, "idx_name")

// Check Index exists
db.Migrator().HasIndex(&User{}, "Name")
db.Migrator().HasIndex(&User{}, "idx_name")

type User struct {
gorm.Model
Name string `gorm:"size:255;index:idx_name,unique"`
Name2 string `gorm:"size:255;index:idx_name_2,unique"`
}
// Rename index name
db.Migrator().RenameIndex(&User{}, "Name", "Name2")
db.Migrator().RenameIndex(&User{}, "idx_name", "idx_name_2")

制約

GORM は、自動マイグレーションまたはテーブル作成時に制約を作成します。詳細は、制約またはデータベースインデックスを参照してください。

Atlas 統合

Atlas は、GORM と公式に統合されたオープンソースのデータベースマイグレーションツールです。

GORM の AutoMigrate 機能はほとんどの場合で機能しますが、場合によってはバージョン管理されたマイグレーション戦略に切り替える必要が出てくるでしょう。

そうなった場合、マイグレーションスクリプトの計画と、それらが実行時に GORM が期待するものと一致していることを確認する責任は、開発者に移ります。

Atlas は、公式のGORM プロバイダーを使用して、開発者向けのデータベーススキーママイグレーションを自動的に計画できます。プロバイダーを設定すると、次を実行してマイグレーションを自動的に計画できます。

atlas migrate diff --env gorm

GORM で Atlas を使用する方法については、公式ドキュメントを参照してください。

その他のマイグレーションツール

GORM を他の Go ベースのマイグレーションツールで使用するために、GORM は役に立つ可能性のある汎用 DB インターフェースを提供します。

// returns `*sql.DB`
db.DB()

詳細は汎用インターフェースを参照してください。

プラチナスポンサー

ゴールドスポンサー

プラチナスポンサー

ゴールドスポンサー