Gorm学习(三)基础:迁移(数据库建表以及字段设置)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 在项目开发中,我们可能会随时调整声明的模型,比如添加字段和索引,使用 GORM 的自动迁移功能,可以始终让我们的数据库表结构保持最新。

前言


感谢开源项目gin-vue-admin,以及1010工作室的视频教程

本人学识尚浅,如有错误,请评论指出,谢谢!

详细可见个人博客:https://linzyblog.netlify.app/


一、迁移概念


在项目开发中,我们可能会随时调整声明的模型,比如添加字段和索引,使用 GORM 的自动迁移功能,可以始终让我们的数据库表结构保持最新。


此外,GORM 还提供了一些迁移接口的方法,可以帮助我们方便操作数据库表、字段和索引。


二、AutoMigrate 自动迁移


AutoMigrate 用于自动迁移你的 schema(模式),保持你的 schema(模式) 是最新的。


注意: AutoMigrate 会创建表、缺失的外键、约束、列和索引。 并且会更改现有列的类型,如果大小、精度、是否为空可以更改。 但不会删除未使用的列,以保护您的数据。(只增不减)


在执行 AutoMigrate时,我们需要先声明模型。


type User struct {
  gorm.Model
  Name string
  Age  uint
}
type Product struct {
  gorm.Model
  Name  string
  Price int
}
type Order struct {
  gorm.Model
  UserID    int
  ProductID int
}


建立数据库连接后,执行 AutoMigrate:


var db *gorm.DB
func init() {
  var err error
  //我这里用到数据库是mysql,需要配置DSN属性[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
  dsn := "root:123456@tcp(127.0.0.1:3306)/go_test?charset=utf8&parseTime=True"
  db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
  if err != nil {
    panic("failed to connect database")
  }
}
func main() {
  db.AutoMigrate(&User{})
  db.AutoMigrate(&User{}, &Product{}, &Order{})
}

50ae867464814d7cbacba46352b2cc30.png


三、Migrator 接口


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


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


一些版本的 MySQL 不支持 rename 列,索引。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)
  // 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
}


1、数据库接口


1)CurrentDatabase 返回当前使用的数据库名


db.Migrator().CurrentDatabase()

db80a6791d464b2480162a27952192db.png


2、数据表接口


操作数据库表,必须先声明模型。


1)CreateTable 创建数据表


err := db.Migrator().CreateTable(&User{})
if err != nil {
  fmt.Printf("创建数据库表失败,错误:%s\n", err)
  return
}
fmt.Println("创建数据库表成功")


创建失败:


bacdf3a19cc34cd3a963ea433a3867f5.png


创建成功:


默认情况下,GORM 会约定使用 ID 作为表的主键,可以通过标签 gorm:"primarykey" 将其它字段设为主键。


通过将多个字段设为主键,以达到创建复合主键,整型字段设为主键,默认为启用 AutoIncrement,如果需要禁用,使用标签 autoIncrement:false。


GORM 约定使用结构体名的复数形式作为表名,不过也可以根据需求修改,可以实现Tabler 接口来更改默认表名,不过这种方式不支持动态变化,它会被缓存下来以便后续使用,如果想要使用动态表名,可以使用Scopes.


GORM 约定使用结构体的字段名作为数据表的字段名,默认GORM 对 struct 字段名使用Snake Case命名风格转换成 MySQL 表字段名(需要转换成小写字母),也可以通过标签 column 修改。


2)HasTable 检查对应的数据表是否存在


isExist := db.Migrator().HasTable(&User{})
//isExist := db.Migrator().HasTable("users")
if !isExist {
  fmt.Printf("users 表不存在\n")
  return
}
fmt.Printf("users 表存在\n")

7e7f2c0e315c4d2badee87a8448b6476.png


3)DropTable 如果存在表则删除(删除时会忽略、删除外键约束)


db.Migrator().DropTable(&User{})
// err := db.Migrator().DropTable("users")
fmt.Printf("users 表删除成功\n")

1e6e76ae0e6345399d68620bcb803c14.png


4)RenameTable 重命名表


// db.Migrator().RenameTable("users", "user_infos")
//若是users表存在则改名为user_infos表,反之亦然
if b := db.Migrator().HasTable(&User{}); b {
  db.Migrator().RenameTable(&User{}, &UserInfo{})
  fmt.Printf("users 表名修改成功\n")
} else {
  db.Migrator().RenameTable(&UserInfo{}, &User{})
  fmt.Printf("user_infos 表名修改成功\n")
}


8376fb46be234d2ea375b473b3f768ff.png


个人推荐用结构体模型来进行以上操作,数据库的结构可以统一固定,这也是迁移的目的。


3、数据表字段接口


操作数据库表字段,必须先声明模型。


1)AddColumn 添加字段


注意:


  • 必须先声明模型。
  • 数据表不存在的字段名,且结构体字段存在。


现在的表结构:


b3f421275d3c4a309551e70611c9969c.png


type User struct {
  Sex bool
}
err := db.Migrator().AddColumn(&User{}, "Sex")
if err != nil {
  fmt.Printf("添加字段错误,err:%s\n", err)
  return
}


6e64c88513f847d78f02965e0a5962b1.png


2)DropColumn 删除字段


err := db.Migrator().DropColumn(&User{}, "Age")
if err != nil {
  fmt.Printf("删除字段错误,err:%s\n", err)
  return
}


78b311c35301473ca7d7cb42d7b86227.png


3)RenameColumn 修改字段名


注意:


  • 必须先声明模型。
  • 修改的字段名在对应的数据表必须存在,修改的字段名和修改后的字段名必须定义在结构体内。


type User struct {
  Name     string
  UserName string
}
err := db.Migrator().RenameColumn(&User{}, "name", "user_name")
if err != nil {
  fmt.Printf("修改字段名错误,err:%s\n", err)
  return
}

0fcdaa96e17f4f3289abd4fa446f1477.png


4)HasColumn 查询字段是否存在


isExistField := db.Migrator().HasColumn(&User{}, "name")
fmt.Printf("name字段是否存在:%t\n", isExistField)
isExistField = db.Migrator().HasColumn(&User{}, "user_name")
fmt.Printf("user_name:%t\n", isExistField)

ef708625dba247d691105c65a626d0ba.png


4、 数据库表的索引接口


1)CreateIndex 为字段创建索引


注意:


  • 必须先声明模型。
  • 必须先在声明模型中使用标签gorm:index定义索引。


type User struct {
  gorm.Model
  Name string `gorm:"size:255;index:idx_name,unique"`
}
// 为 Name 字段创建索引,两种方法都可以
db.Migrator().CreateIndex(&User{}, "Name")
db.Migrator().CreateIndex(&User{}, "idx_name")

f846e698c8f14cecb46655128eee67b1.png


2)DropIndex 为字段删除索引


db.Migrator().DropIndex(&User{}, "Name")
db.Migrator().DropIndex(&User{}, "idx_name")

b7a5871425e643a1906c6c6ffaa506d0.png


3)HasIndex 检查索引是否存在


isExists := db.Migrator().HasIndex(&User{}, "idx_name")
fmt.Printf("idex_name是否存在:%t\n", isExists)
db.Migrator().CreateIndex(&User{}, "idx_name")
isExists = db.Migrator().HasIndex(&User{}, "idx_name")
fmt.Printf("idex_name是否存在:%t\n", isExists)

468623eb6c6341ac8647ccd712235180.png


4)RenameIndex 修改索引名


注意:


  • 必须先声明模型。
  • 必须先在声明模型中使用标签gorm:index定义索引。


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

cea6547308934fa2b8790d985376da24.png


四、小结


Gorm的迁移接口功能很丰富,AutoMigrate 就适用于大多数的迁移,如果需要更加个性化的迁移工具 ,GORM 提供的一个通用数据库接口。


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


迁移接口的方法,确实给开发工作带来了方便,但是个人建议除非特殊原因,否则尽量通过在声明模型中修改数据库表的字段和索引。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7天前
|
SQL NoSQL 关系型数据库
数据库学习
【10月更文挑战第8天】
14 1
|
8天前
|
关系型数据库 MySQL Java
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
这篇文章是关于如何使用Django框架配置MySQL数据库,创建模型实例,并自动或手动创建数据库表,以及对这些表进行操作的详细教程。
32 0
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
|
9天前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
14 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
9天前
|
Java 关系型数据库 MySQL
springboot学习四:springboot链接mysql数据库,使用JdbcTemplate 操作mysql
这篇文章是关于如何使用Spring Boot框架通过JdbcTemplate操作MySQL数据库的教程。
11 0
springboot学习四:springboot链接mysql数据库,使用JdbcTemplate 操作mysql
|
14天前
|
存储 分布式计算 数据库
阿里云国际版设置数据库云分析工作负载的 ClickHouse 版
阿里云国际版设置数据库云分析工作负载的 ClickHouse 版
|
16天前
|
应用服务中间件 数据库
Tomcat 的数据库连接池设置与应用
Tomcat 的数据库连接池设置与应用
32 3
|
16天前
|
关系型数据库 MySQL 数据库
使用Docker部署的MySQL数据库如何设置忽略表名大小写?
【10月更文挑战第1天】使用Docker部署的MySQL数据库如何设置忽略表名大小写?
46 1
|
10天前
|
SQL 监控 测试技术
全面解析SQL数据库迁移:步骤、挑战与最佳实践a8u.0335pw.com
随着信息技术的快速发展,数据库迁移已成为企业和组织在IT领域经常面临的一项任务。数据库迁移涉及到数据的转移、转换和适应新环境的过程,特别是在使用SQL数据库时。本文将详细介绍SQL数据库迁移的过程,探讨其面临的挑战,并分享一些最佳实践。一、数据库迁移概述数据库迁移是指将数据库从一个环境迁移到另一个环
|
12天前
|
关系型数据库 MySQL 数据库
mysql关系型数据库的学习
mysql关系型数据库的学习
14 0
|
17天前
|
存储 NoSQL Java
使用 Java 了解和学习 NoSQL 数据库:三个主要优势
使用 Java 了解和学习 NoSQL 数据库:三个主要优势
9 0