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()


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

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3天前
|
存储 NoSQL MongoDB
数据库数据恢复—MongoDB数据库迁移过程中丢失文件的数据恢复案例
某单位一台MongoDB数据库由于业务需求进行了数据迁移,数据库迁移后提示:“Windows无法启动MongoDB服务(位于 本地计算机 上)错误1067:进程意外终止。”
|
1月前
|
运维 关系型数据库 MySQL
体验领礼啦!体验自建数据库迁移到阿里云数据库RDS,领取桌面置物架!
「技术解决方案【Cloud Up 挑战赛】」上线!本方案介绍如何将自建数据库平滑迁移至云数据库RDS,解决业务增长带来的运维难题。通过使用RDS MySQL,您可获得稳定、可靠和安全的企业级数据库服务,专注于核心业务发展。完成任务即可领取桌面置物架,每个工作日限量50个,先到先得。
|
2月前
|
弹性计算 关系型数据库 数据库
自建数据库迁移到云数据库实操
本课程详细介绍了自建数据库迁移到阿里云RDS的实操步骤。主要内容包括:创建实例资源、安全设置、配置自建的MySQL数据库、数据库的迁移、从自建数据库切换到RDS以及清理资源。通过这些步骤,学员可以掌握如何将自建数据库安全、高效地迁移到云端,并确保应用的正常运行。
166 26
|
2月前
|
弹性计算 关系型数据库 数据库
从自建到云端,数据库迁移全攻略
本文详细介绍了将自建数据库迁移至阿里云RDS的全过程,涵盖WordPress网站安装、数据库迁移配置及验证等步骤。通过DTS数据传输服务,实现库表结构、全量和增量数据的无缝迁移,确保业务连续性和数据一致性。方案具备零成本维护、高可用性(最高99.99%)、性能优化及全面的数据安全保障等核心优势。此外,提供了详细的图文教程,帮助用户快速上手并完成迁移操作,确保业务稳定运行。点击文末“阅读原文”了解更多详情及参与活动赢取精美礼品。
166 13
|
2月前
|
存储 JSON NoSQL
学习 MongoDB:打开强大的数据库技术大门
MongoDB 是一个基于分布式文件存储的文档数据库,由 C++ 编写,旨在为 Web 应用提供可扩展的高性能数据存储解决方案。它与 MySQL 类似,但使用文档结构而非表结构。核心概念包括:数据库(Database)、集合(Collection)、文档(Document)和字段(Field)。MongoDB 使用 BSON 格式存储数据,支持多种数据类型,如字符串、整数、数组等,并通过二进制编码实现高效存储和传输。BSON 文档结构类似 JSON,但更紧凑,适合网络传输。
82 15
|
2月前
|
弹性计算 安全 关系型数据库
活动实践 | 自建数据库迁移到云数据库
通过阿里云RDS,用户可获得稳定、安全的企业级数据库服务,无需担心数据库管理与维护。该方案使用RDS确保数据库的可靠性、可用性和安全性,结合ECS和DTS服务,实现自建数据库平滑迁移到云端,支持WordPress等应用的快速部署与运行。通过一键部署模板,用户能迅速搭建ECS和RDS实例,完成数据迁移及应用上线,显著提升业务灵活性和效率。
|
2月前
|
前端开发 JavaScript 数据库
获取数据库中字段的数据作为下拉框选项
获取数据库中字段的数据作为下拉框选项
66 5
|
2月前
|
运维 关系型数据库 MySQL
自建数据库迁移到云数据库RDS
本次课程由阿里云数据库团队的凡珂分享,主题为自建数据库迁移至云数据库RDS MySQL版。课程分为四部分:1) 传统数据库部署方案及痛点;2) 选择云数据库RDS MySQL的原因;3) 数据库迁移方案和产品选型;4) 线上活动与权益。通过对比自建数据库的局限性,介绍了RDS MySQL在可靠性、安全性、性价比等方面的优势,并详细讲解了使用DTS(数据传输服务)进行平滑迁移的步骤。此外,还提供了多种优惠活动信息,帮助用户降低成本并享受云数据库带来的便利。
102 6
|
2月前
|
安全 关系型数据库 MySQL
体验自建数据库迁移到云数据库RDS,领取桌面置物架!
「技术解决方案【Cloud Up 挑战赛】」正式开启!本方案旨在帮助用户将自建数据库平滑迁移至阿里云RDS MySQL,享受稳定、高效、安全的数据库服务,助力业务快速发展。完成指定任务即可赢取桌面置物架等奖励,限量供应,先到先得。活动时间:2024年12月3日至12月31日16点。
|
3月前
|
关系型数据库 MySQL Linux
Linux系统如何设置自启动服务在MySQL数据库启动后执行?
【10月更文挑战第25天】Linux系统如何设置自启动服务在MySQL数据库启动后执行?
230 3

热门文章

最新文章