迁移

自动迁移

自动迁移您的模式,以保持您的模式是最新的。

注意: AutoMigrate 将创建表、缺少的外键、约束、列和索引。如果现有列的大小、精度、可空性发生变化,它将更改其类型。它不会删除未使用的列,以保护您的数据。

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,
})

迁移器接口

GORM 提供了一个迁移器接口,其中包含每个数据库的统一 API 接口,可用于构建独立于数据库的迁移,例如

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
}

当前数据库

返回当前使用的数据库名称

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 Provider自动为开发人员规划数据库模式迁移。配置提供程序后,您可以通过运行以下命令自动规划迁移

atlas migrate diff --env gorm

要了解如何将 Atlas 与 GORM 一起使用,请查看官方文档

其他迁移工具

为了将 GORM 与其他基于 Go 的迁移工具一起使用,GORM 提供了一个通用的数据库接口,这对您可能会有所帮助。

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

有关更多详细信息,请参阅通用接口

铂金赞助商

黄金赞助商

铂金赞助商

黄金赞助商