Go 語言編程 — gorm 數據庫版本遷移

      網友投稿 1300 2025-03-31

      目錄

      文章目錄

      目錄

      前言

      AutoMigrate

      示例

      Migrator 接口(DDL 操作方法)

      表操作

      列操作

      約束操作

      索引操作

      數據庫版本控制

      參考文檔

      前言

      本文示例為 GORM V2.0 版本。

      AutoMigrate

      GORM 的 AutoMigrate() 方法用于自動遷移 ORM 的 Schemas。所謂 “遷移” 就是刷新數據庫中的表格定義,使其保持最新(只增不減)。

      AutoMigrate 會創建(新的)表、缺少的外鍵、約束、列和索引,并且會更改現有列的類型(如果其大小、精度、是否為空可更改的話)。但不會刪除未使用的列,以保護現存的數據。

      // 初始化一張表 db.AutoMigrate(&User{}) // 初始化多張表 db.AutoMigrate(&User{}, &Product{}, &Order{}) // 創建表的同時進行表屬性配置 db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})

      1

      2

      3

      4

      5

      6

      7

      8

      在 2.0 版本中,AutoMigrate 還會自動創建數據庫表的約束,包括:外鍵約束。這在 1.9 版本中,則需要顯示的通過 sql tag 來完成。

      2.0 還支持在初始化時禁用此功能:

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

      1

      2

      3

      示例

      以 SQLite 數據庫存儲為例。

      V1 Schema

      type Product struct { gorm.Model Code string Price string } // 初始化 V1 db.AutoMigrate(&Product{})

      1

      2

      3

      4

      5

      6

      7

      8

      其在數據庫的存儲格式為:

      V2 Schema:新增了一個 Age 字段

      type Product struct { gorm.Model Code string Price string Age string } // 更新 V2 db.AutoMigrate(&Product{})

      1

      2

      3

      4

      5

      6

      7

      8

      9

      數據庫會自動為 products 表新增 age 列,舊數據記錄的 age 列值為空(NULL),新數據記錄的 age 列值可以不為空:

      V3 Schema:刪除了 Price 和 Age 字段

      type Product struct { gorm.Model Code string } // 更新 V3 db.AutoMigrate(&Product{})

      1

      2

      3

      4

      5

      6

      7

      數據庫不會自動為 products 表刪減 price 和 age 列,舊數據記錄依舊存在且可以使用,新數據紀錄的 price 和 age 的列值為空(NULL):

      Migrator 接口(DDL 操作方法)

      如果 AutoMigrate 還不足以滿足特殊的需求,那么 GORM 還提供了 Migrator 接口,可用來為 ORM Schemas 實現自定義的遷移邏輯。

      Migrator 還為不同類型的數據庫提供了統一的 API 抽象,例如:SQLite 不支持 ALTER COLUMN、DROP COLUMN 等 SQL 子句,所以當我們調用 Migrator API 試圖修改表結構時,GORM 會自定為在 SQLite 創建一張新表、并復制所有數據,然后刪除舊表、重命名新表。

      再例如:舊版本的 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 // Columns AddColumn(dst interface{}, field string) error DropColumn(dst interface{}, field string) error AlterColumn(dst interface{}, field string) error HasColumn(dst interface{}, field string) bool RenameColumn(dst interface{}, oldName, field string) error MigrateColumn(dst interface{}, field *schema.Field, columnType *sql.ColumnType) error ColumnTypes(dst interface{}) ([]*sql.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

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      表操作

      // 為 `User` 創建表 db.Migrator().CreateTable(&User{}) // 將 "ENGINE=InnoDB" 添加到創建 `User` 的 SQL 里去 db.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&User{}) // 檢查 `User` 對應的表是否存在 db.Migrator().HasTable(&User{}) db.Migrator().HasTable("users") // 如果存在表則刪除(刪除時會忽略、刪除外鍵約束) db.Migrator().DropTable(&User{}) db.Migrator().DropTable("users") // 重命名表 db.Migrator().RenameTable(&User{}, &UserInfo{}) db.Migrator().RenameTable("users", "user_infos")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      列操作

      type User struct { Name string } // 添加 name 字段 db.Migrator().AddColumn(&User{}, "Name") // 刪除 name 字段 db.Migrator().DropColumn(&User{}, "Name") // 修改 name 字段 db.Migrator().AlterColumn(&User{}, "Name") // 檢查字段是否存在 db.Migrator().HasColumn(&User{}, "Name") type User struct { Name string NewName string } // 重命名字段 db.Migrator().RenameColumn(&User{}, "Name", "NewName") db.Migrator().RenameColumn(&User{}, "name", "new_name") // 獲取字段類型 db.Migrator().ColumnTypes(&User{}) ([]*sql.ColumnType, error)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      約束操作

      Go 語言編程 — gorm 數據庫版本遷移

      包括基本的數據完整性約束類型。

      type UserIndex struct { Name string `gorm:"check:name_checker,name <> 'jinzhu'"` } // 創建約束 db.Migrator().CreateConstraint(&User{}, "name_checker") // 刪除約束 db.Migrator().DropConstraint(&User{}, "name_checker") // 檢查約束是否存在 db.Migrator().HasConstraint(&User{}, "name_checker")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      索引操作

      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") // 為 Name 字段刪除索引 db.Migrator().DropIndex(&User{}, "Name") db.Migrator().DropIndex(&User{}, "idx_name") // 檢查索引是否存在 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"` } // 修改索引名 db.Migrator().RenameIndex(&User{}, "Name", "Name2") db.Migrator().RenameIndex(&User{}, "idx_name", "idx_name_2")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      數據庫版本控制

      需要注意的是,GORM 雖然提供了不錯的數據庫遷移功能,但是距離理想的 “版本控制” 仍有距離。不支持,包括:版本記錄、版本回退、版本選擇。這些都需要開發者自行封裝。

      參考文檔

      https://gorm.io/zh_CN/docs/migration.html

      https://davidchan0519.github.io/2019/05/06/gorm-automigrate/

      Go 數據庫

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:怎么固定word表格不改變大?。╳ord怎么設置表格大小不變)
      下一篇:文檔插入表格,離上一行文字很遠,表格上提就把文字擠到下面了,怎么辦
      相關文章
      亚洲综合成人婷婷五月网址| 国产亚洲精品第一综合| 亚洲精品国产av成拍色拍| 久久久亚洲精品国产| 亚洲国产一成久久精品国产成人综合| 亚洲午夜无码久久| 亚洲综合色丁香婷婷六月图片| 亚洲国产精品综合久久20| 亚洲午夜精品一区二区公牛电影院| 亚洲视频中文字幕在线| 亚洲成人福利网站| 亚洲制服在线观看| 亚洲AV无码专区在线亚| 亚洲自国产拍揄拍| 亚洲一区二区三区成人网站 | 亚洲1区1区3区4区产品乱码芒果| 亚洲的天堂av无码| 亚洲伦理一二三四| 亚洲kkk4444在线观看| 亚洲av无码日韩av无码网站冲| 在线亚洲v日韩v| 亚洲色偷偷综合亚洲AV伊人| 亚洲国产综合人成综合网站| 国产91精品一区二区麻豆亚洲| 亚洲香蕉成人AV网站在线观看| 国产V亚洲V天堂A无码| 亚洲人成影院在线| 亚洲国产成人手机在线电影bd| 亚洲男人的天堂久久精品| 亚洲日韩一中文字暮| 亚洲成a人无码亚洲成www牛牛| 久久亚洲中文无码咪咪爱| 亚洲不卡AV影片在线播放| 日韩色视频一区二区三区亚洲| 亚洲精品乱码久久久久久蜜桃| 亚洲午夜久久久影院| 亚洲国产精品第一区二区| 亚洲国产成人手机在线电影bd | 亚洲午夜福利717| 亚洲高清在线播放| 亚洲欧洲日产韩国在线|