GoravelGoravel
首页
视频
  • English
  • 简体中文
GitHub
首页
视频
  • English
  • 简体中文
GitHub
  • 前言

    • 升级指南

      • 从 v1.14 升级到 v1.15
      • 从 v1.13 升级到 v1.14
      • 历史版本升级
    • 贡献指南
    • 优秀扩展包
  • 入门指南

    • 安装
    • 配置信息
    • 文件夹结构
    • 编译
  • 核心架构

    • 请求周期
    • 服务容器
    • 服务提供者
    • Facades
  • 基本功能

    • 路由
    • HTTP 中间件
    • 控制器
    • 请求
    • 响应
    • 视图
    • Grpc
    • Session
    • 表单验证
    • 日志
  • 综合话题

    • Artisan 命令行
    • 缓存系统
    • 事件系统
    • 文件储存
    • 邮件
    • 队列
    • 任务调度
    • 本地化
    • 扩展包开发
    • 颜色
    • Strings
    • 辅助函数
  • 安全相关

    • 用户验证
    • 用户授权
    • 加密解密
    • 哈希
  • ORM

    • 快速入门
    • 模型关联
    • 数据库迁移
    • 数据填充
    • 模型工厂
  • 测试相关

    • 快速入门
    • HTTP Tests
    • Mock

数据库迁移

  • 简介
  • 配置
  • 生成迁移
    • 快捷生成
  • 迁移结构
    • Go 语言迁移
    • SQL 迁移
  • 注册迁移
  • 执行迁移
  • 回滚迁移
    • 使用单个命令同时进行回滚和迁移操作
    • 删除所有表然后执行迁移
  • Tables
    • 创建表
    • 检查表 / 列是否存在
    • 数据库连接
    • 更新表
    • 重命名 / 删除表
  • 字段
    • 可用的字段类型
    • 列修饰符
    • 删除列
  • 索引
    • 创建索引
    • 重命名索引
    • 删除索引
    • 外键约束
    • 删除外键

简介

当多人协作开发应用程序时,如果同步数据库结构没有一个统一的规范,以保证所有人的本地数据都是一致的,那将是灾难。数据库迁移就是为了解决这个问题,将数据库的结构进行版本控制,以保证所有开发人员的数据库结构的一致性。

配置

数据库迁移文件存放在 database/migrations 目录下,你可以在 config/database.go 文件中配置数据库连接信息。当前支持 Go 语言迁移和 SQL 迁移两个驱动,但 SQL 迁移将在后续版本中移除。

// Available Drivers: "default", "sql"
"migrations": map[string]any{
  "driver": "default",
  // You can cumstomize the table name of migrations
  "table":  "migrations",
},

生成迁移

使用 make:migration 命令来创建迁移:

go run . artisan make:migration create_users_table

该命令会在 database/migrations 目录下生成迁移文件,所有迁移文件都以一个时间戳为开头,Goravel 将以此作为迁移文件的执行顺序。

快捷生成

使用 create_users_table 将会自动生成包含 users 基础结构的表,实现原理是根据正则进行匹配:

^create_(\w+)_table$
^create_(\w+)$

使用 add_avatar_to_users_table 将会自动生成向 users 表增加字段的结构,实现原理是根据正则进行匹配:

_(to|from|in)_(\w+)_table$
_(to|from|in)_(\w+)$

未匹配到上述情况时,框架会生成一个空的迁移文件。

迁移结构

Go 语言迁移

迁移类包含两个方法:Up 和 Down。Up 方法用于向数据库中添加新表、列或索引,而 Down 方法用于撤销 Up 方法执行的操作。在这两种方法中,可以使用 facades.Schema() 来创建和操作数据库表,起可用方法详见文档。以下迁移会创建一个 users 表:

package migrations

import (
	"github.com/goravel/framework/contracts/database/schema"
	"github.com/goravel/framework/facades"
)

type M20241207095921CreateUsersTable struct {
}

// Signature The unique signature for the migration.
func (r *M20241207095921CreateUsersTable) Signature() string {
	return "20241207095921_create_users_table"
}

// Up Run the migrations.
func (r *M20241207095921CreateUsersTable) Up() error {
	if !facades.Schema().HasTable("users") {
		return facades.Schema().Create("users", func(table schema.Blueprint) {
			table.ID()
			table.String("name").Nullable()
			table.String("email").Nullable()
			table.Timestamps()
		})
	}

	return nil
}

// Down Reverse the migrations.
func (r *M20241207095921CreateUsersTable) Down() error {
	return facades.Schema().DropIfExists("users")
}

设置迁移连接

如果迁移将与应用程序默认数据库连接以外的数据库连接进行交互,你可以使用迁移的 Connection 方法:

func (r *M20241207095921CreateUsersTable) Connection() string {
  return "connection-name"
}

SQL 迁移

迁移命令会同时生成两个迁移文件:***.up.sql、***.down.sql,分别对应执行、回滚。你可以在这两个文件中直接编写 SQL 语句。

-- ***.up.sql
CREATE TABLE `users` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `email` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- ***.down.sql
DROP TABLE `users`;

注册迁移

使用 Go 语言迁移时,迁移文件生成后需要再在 database/kernel.go 文件中注册迁移文件:

// database/kernel.go
func (kernel Kernel) Migrations() []schema.Migration {
	return []schema.Migration{
		&migrations.M20241207095921CreateUsersTable{},
	}
}

SQL 迁移不需要注册,框架会自动扫描 database/migrations 目录下的 SQL 文件。

执行迁移

执行 Artisan 命令 migrate,来运行所有未执行过的迁移:

go run . artisan migrate

如果你想查看目前的迁移状态,可以使用 migrate:status Artisan 命令:

go run . artisan migrate:status

回滚迁移

如果要回滚最后一次迁移操作,可以使用 Artisan 命令 rollback。该命令会回滚最后「一批」的迁移,这可能包含多个迁移文件:

go run . artisan migrate:rollback

通过向 rollback 命令加上 step 参数,可以回滚指定数量的迁移。例如,以下命令将回滚最后五个迁移:

go run . artisan migrate:rollback --step=5

命令 migrate:reset 会回滚应用已运行过的所有迁移:

go run . artisan migrate:reset

使用单个命令同时进行回滚和迁移操作

命令 migrate:refresh 首先会回滚已运行过的所有迁移,随后会执行 migrate。这一命令可以高效地重建你的整个数据库:

go run . artisan migrate:refresh

通过在命令 refresh 中使用 step 参数,你可以回滚并重新执行指定数量的迁移操作。例如,下列命令会回滚并重新执行最后五个迁移操作:

go run . artisan migrate:refresh --step=5

删除所有表然后执行迁移

命令 migrate:fresh 会删去数据库中的所有表,随后执行命令 migrate:

go run . artisan migrate:fresh

Tables

创建表

facades.Schema().Create("users", func(table schema.Blueprint) {
  table.ID()
  table.String("name").Nullable()
  table.String("email").Nullable()
  table.Timestamps()
})

检查表 / 列是否存在

if facades.Schema().HasTable("users") {}
if facades.Schema().HasColumn("users", "email") {}
if facades.Schema().HasColumns("users", []string{"name", "email"}) {}
if facades.Schema().HasIndex("users", "email_unique") {}

数据库连接

facades.Schema().Connection("sqlite").Create("users", func(table schema.Blueprint) {
  table.ID()
})

更新表

facades.Schema().Table("users", func(table schema.Blueprint) {
  table.String("name").Nullable()
})

重命名 / 删除表

facades.Schema().Rename("users", "new_users")
facades.Schema().Drop("users")
facades.Schema().DropIfExists("users")

字段

可用的字段类型

BigIncrementsBigIntegerBooleanChar
DateDateTimeDateTimeTzDecimal
DoubleEnumFloatID
IncrementsIntegerIntegerIncrementsJson
IncrementsLongTextMediumIncrementsMediumInteger
MediumTextSmallIncrementsSmallIntegerSoftDeletes
SoftDeletesTzStringTextTime
TimeTzTimestampTimestampsTimestampsTz
TimestampTzUnsignedBigIntegerTinyIncrementsTinyInteger
TinyTextUnsignedIntegerUnsignedMediumIntegerUnsignedSmallInteger
UnsignedTinyInteger

Enum

创建一个 Enum 字段,该字段在 Mysql 中可以根据 []any 中的类型进行储存,但在 Postgres, Sqlite 和 Sqlserver 数据库中都是 String 类型。

table.Enum("difficulty", []any{"easy", "hard"})
table.Enum("num", []any{1, 2})

ID

ID 方法是 BigIncrements 方法的别名。默认情况下,该方法将创建一个 id 列;但是,如果你想要为该列分配一个不同的名称,可以传递一个列名称:

table.ID()
table.ID("user_id")

SoftDeletes

SoftDeletes 方法添加了一个可以为空的 deleted_at TIMESTAMP 列。此列旨在存储 Orm 「软删除」功能所需的 deleted_at 时间戳:

table.SoftDeletes()

自定义字段

如果你正在使用框架尚不支持的字段类型,可以通过 Column 方法自定义字段类型:

table.Column("geometry", "geometry")

列修饰符

除了上面列出的列类型之外,当给数据库表添加一个列时,你还可以给列添加「修饰符」。例如,要使列可以「为空」,你可以使用 Nullable 方法:

facades.Schema().Table("users", func(table schema.Blueprint) {
  table.String("name").Nullable()
})

以下表格包含所有可用的列修饰符:

修饰符描述
.AutoIncrement()设置整数列为自动增长的(主键)
.Comment("my comment")向列添加注释(MySQL / PostgreSQL)
.Default(value)为列指定「默认」值
.Nullable()允许插入 NULL 值到列中
.Unsigned()设置整数列为 UNSIGNED(仅限 MySQL)
.UseCurrent()设置时间戳列使用 CURRENT_TIMESTAMP 作为默认值
.UseCurrentOnUpdate()设置记录更新时,时间戳列使用 CURRENT_TIMESTAMP(仅限 MySQL)

删除列

facades.Schema().Table("users", func(table schema.Blueprint) {
  table.DropColumn("name")
  table.DropColumn("name", "age")
})

索引

创建索引

facades.Schema().Table("users", func(table schema.Blueprint) {
  // 添加主键
  table.Primary("id")
  // 添加复合主键
  table.Primary("id", "name")

  // 添加唯一索引
  table.Unique("name")
  table.Unique("name", "age")

  // 添加普通索引
  table.Index("name")
  table.Index("name", "age")

  // 添加全文索引
  table.FullText("name")
  table.FullText("name", "age")
})

重命名索引

facades.Schema().Table("users", func(table schema.Blueprint) {
  table.RenameIndex("users_name_index", "users_name")
})

删除索引

facades.Schema().Table("users", func(table schema.Blueprint) {
  table.DropPrimary("id")
  table.DropUnique("name")
  table.DropUniqueByName("name_unique")
  table.DropIndex("name")
  table.DropIndexByName("name_index")
  table.DropFullText("name")
  table.DropFullTextByName("name_fulltext")
})

外键约束

facades.Schema().Table("posts", func(table schema.Blueprint) {
  table.UnsignedBigInteger("user_id")
  table.Foreign("user_id").References("id").On("users")
})

删除外键

facades.Schema().Table("users", func(table schema.Blueprint) {
  table.DropForeign("user_id")
  table.DropForeignByName("user_id_foreign")
})
Edit this page
Prev
模型关联
Next
数据填充