AutoMigrate

AutoMigrate 用于自动迁移您的 schema,保持您的 schema 是最新的。

注意: AutoMigrate 会创建表、缺失的外键、约束、列和索引。 It will change existing column’s type if its size, precision changed, or if it’s changing from non-nullable to nullable. 出于保护您数据的目的,它 不会 删除未使用的列

  1. db.AutoMigrate(&User{})
  2. db.AutoMigrate(&User{}, &Product{}, &Order{})
  3. // 创建表时添加后缀
  4. db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})

注意 AutoMigrate 会自动创建数据库外键约束,您可以在初始化时禁用此功能,例如:

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

Migrator 接口

GORM 提供了 Migrator 接口,该接口为每个数据库提供了统一的 API 接口,可用来为您的数据库构建独立迁移,例如:

SQLite 不支持 ALTER COLUMNDROP COLUMN,当你试图修改表结构,GORM 将创建一个新表、复制所有数据、删除旧表、重命名新表。

一些版本的 MySQL 不支持 rename 列,索引。GORM 将基于您使用 MySQL 的版本执行不同 SQL

  1. type Migrator interface {
  2. // AutoMigrate
  3. AutoMigrate(dst ...interface{}) error
  4. // Database
  5. CurrentDatabase() string
  6. FullDataTypeOf(*schema.Field) clause.Expr
  7. // Tables
  8. CreateTable(dst ...interface{}) error
  9. DropTable(dst ...interface{}) error
  10. HasTable(dst interface{}) bool
  11. RenameTable(oldName, newName interface{}) error
  12. GetTables() (tableList []string, err error)
  13. // Columns
  14. AddColumn(dst interface{}, field string) error
  15. DropColumn(dst interface{}, field string) error
  16. AlterColumn(dst interface{}, field string) error
  17. MigrateColumn(dst interface{}, field *schema.Field, columnType ColumnType) error
  18. HasColumn(dst interface{}, field string) bool
  19. RenameColumn(dst interface{}, oldName, field string) error
  20. ColumnTypes(dst interface{}) ([]ColumnType, error)
  21. // Views
  22. CreateView(name string, option ViewOption) error
  23. DropView(name string) error
  24. // Constraints
  25. CreateConstraint(dst interface{}, name string) error
  26. DropConstraint(dst interface{}, name string) error
  27. HasConstraint(dst interface{}, name string) bool
  28. // Indexes
  29. CreateIndex(dst interface{}, name string) error
  30. DropIndex(dst interface{}, name string) error
  31. HasIndex(dst interface{}, name string) bool
  32. RenameIndex(dst interface{}, oldName, newName string) error
  33. }

当前数据库

返回当前使用的数据库名

  1. db.Migrator().CurrentDatabase()

  1. // 为 `User` 创建表
  2. db.Migrator().CreateTable(&User{})
  3. // 将 "ENGINE=InnoDB" 添加到创建 `User` 的 SQL 里去
  4. db.Set("gorm:table_options", "ENGINE=InnoDB").Migrator().CreateTable(&User{})
  5. // 检查 `User` 对应的表是否存在
  6. db.Migrator().HasTable(&User{})
  7. db.Migrator().HasTable("users")
  8. // 如果存在表则删除(删除时会忽略、删除外键约束)
  9. db.Migrator().DropTable(&User{})
  10. db.Migrator().DropTable("users")
  11. // 重命名表
  12. db.Migrator().RenameTable(&User{}, &UserInfo{})
  13. db.Migrator().RenameTable("users", "user_infos")

  1. type User struct {
  2. Name string
  3. }
  4. // 添加 name 字段
  5. db.Migrator().AddColumn(&User{}, "Name")
  6. // 删除 name 字段
  7. db.Migrator().DropColumn(&User{}, "Name")
  8. // 修改 name 字段
  9. db.Migrator().AlterColumn(&User{}, "Name")
  10. // 检查 name 字段是否存在
  11. db.Migrator().HasColumn(&User{}, "Name")
  12. type User struct {
  13. Name string
  14. NewName string
  15. }
  16. // 字段重命名
  17. db.Migrator().RenameColumn(&User{}, "Name", "NewName")
  18. db.Migrator().RenameColumn(&User{}, "name", "new_name")
  19. // 字段类型
  20. db.Migrator().ColumnTypes(&User{}) ([]gorm.ColumnType, error)
  21. type ColumnType interface {
  22. Name() string
  23. DatabaseTypeName() string // varchar
  24. ColumnType() (columnType string, ok bool) // varchar(64)
  25. PrimaryKey() (isPrimaryKey bool, ok bool)
  26. AutoIncrement() (isAutoIncrement bool, ok bool)
  27. Length() (length int64, ok bool)
  28. DecimalSize() (precision int64, scale int64, ok bool)
  29. Nullable() (nullable bool, ok bool)
  30. Unique() (unique bool, ok bool)
  31. ScanType() reflect.Type
  32. Comment() (value string, ok bool)
  33. DefaultValue() (value string, ok bool)
  34. }

Views

Create views by ViewOption. About ViewOption:

  • Query is a subquery, which is required.
  • If Replace is true, exec CREATE OR REPLACE otherwise exec CREATE.
  • If CheckOption is not empty, append to sql, e.g. WITH LOCAL CHECK OPTION.

NOTE SQLite currently does not support Replace in ViewOption

  1. query := db.Model(&User{}).Where("age > ?", 20)
  2. // Create View
  3. db.Migrator().CreateView("users_pets", gorm.ViewOption{Query: query})
  4. // CREATE VIEW `users_view` AS SELECT * FROM `users` WHERE age > 20
  5. // Create or Replace View
  6. db.Migrator().CreateView("users_pets", gorm.ViewOption{Query: query, Replace: true})
  7. // CREATE OR REPLACE VIEW `users_pets` AS SELECT * FROM `users` WHERE age > 20
  8. // Create View With Check Option
  9. db.Migrator().CreateView("users_pets", gorm.ViewOption{Query: query, CheckOption: "WITH CHECK OPTION"})
  10. // CREATE VIEW `users_pets` AS SELECT * FROM `users` WHERE age > 20 WITH CHECK OPTION
  11. // Drop View
  12. db.Migrator().DropView("users_pets")
  13. // DROP VIEW IF EXISTS "users_pets"

Constraints

  1. type UserIndex struct {
  2. Name string `gorm:"check:name_checker,name <> 'jinzhu'"`
  3. }
  4. // Create constraint
  5. db.Migrator().CreateConstraint(&User{}, "name_checker")
  6. // Drop constraint
  7. db.Migrator().DropConstraint(&User{}, "name_checker")
  8. // Check constraint exists
  9. db.Migrator().HasConstraint(&User{}, "name_checker")

Create foreign keys for relations

  1. type User struct {
  2. gorm.Model
  3. CreditCards []CreditCard
  4. }
  5. type CreditCard struct {
  6. gorm.Model
  7. Number string
  8. UserID uint
  9. }
  10. // create database foreign key for user & credit_cards
  11. db.Migrator().CreateConstraint(&User{}, "CreditCards")
  12. db.Migrator().CreateConstraint(&User{}, "fk_users_credit_cards")
  13. // ALTER TABLE `credit_cards` ADD CONSTRAINT `fk_users_credit_cards` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
  14. // check database foreign key for user & credit_cards exists or not
  15. db.Migrator().HasConstraint(&User{}, "CreditCards")
  16. db.Migrator().HasConstraint(&User{}, "fk_users_credit_cards")
  17. // drop database foreign key for user & credit_cards
  18. db.Migrator().DropConstraint(&User{}, "CreditCards")
  19. db.Migrator().DropConstraint(&User{}, "fk_users_credit_cards")

Indexes

  1. type User struct {
  2. gorm.Model
  3. Name string `gorm:"size:255;index:idx_name,unique"`
  4. }
  5. // Create index for Name field
  6. db.Migrator().CreateIndex(&User{}, "Name")
  7. db.Migrator().CreateIndex(&User{}, "idx_name")
  8. // Drop index for Name field
  9. db.Migrator().DropIndex(&User{}, "Name")
  10. db.Migrator().DropIndex(&User{}, "idx_name")
  11. // Check Index exists
  12. db.Migrator().HasIndex(&User{}, "Name")
  13. db.Migrator().HasIndex(&User{}, "idx_name")
  14. type User struct {
  15. gorm.Model
  16. Name string `gorm:"size:255;index:idx_name,unique"`
  17. Name2 string `gorm:"size:255;index:idx_name_2,unique"`
  18. }
  19. // Rename index name
  20. db.Migrator().RenameIndex(&User{}, "Name", "Name2")
  21. db.Migrator().RenameIndex(&User{}, "idx_name", "idx_name_2")

约束

GORM creates constraints when auto migrating or creating table, see Constraints or Database Indexes for details

Atlas Integration

Atlas is an open-source database migration tool that has an official integration with GORM.

While GORM’s AutoMigrate feature works in most cases, at some point you may need to switch to a versioned migrations strategy.

Once this happens, the responsibility for planning migration scripts and making sure they are in line with what GORM expects at runtime is moved to developers.

Atlas can automatically plan database schema migrations for developers using the official GORM Provider. After configuring the provider you can automatically plan migrations by running:

  1. atlas migrate diff --env gorm

To learn how to use Atlas with GORM, check out the official documentation.

Other Migration Tools

To use GORM with other Go-based migration tools, GORM provides a generic DB interface that might be helpful for you.

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

Refer to Generic Interface for more details.