GoでGORM
を使わずにDB設計を行っていたのですが、どうにかデータベースのカラムだけを変更することがしたいと考えた時に、Djangoでマイグレーション
を行っていたことを思い出したので,今回どうやってGoでマイグレーションを行うか調べてみました。
そもそもマイグレーションとは
マイグレーション
とは、一般的に移行という意味を持っています。
今回行う`データベースマイグレーション`とは、データベースの定義を自動的に作成・管理することを指します。
従来の直接データベースに入って操作していたデータベース定義をスクリプトで操作することができます。
golang-migrate
でマイグレーションしてみる。
まず、golang-migrateのcliツールインストールします。
インストール
brew install golang-migrate
windowsのパッケージマネージャーとかは使ったことないのですいません
以下のコマンドで入っているかを確認します。
migrate --version
マイグレーションファイルを作成してみる
テーブル作成
実際にテーブル定義をしていこうと思います。
下の構造体のようにテーブル定義をしていこうと思います。
type Music struct {
ID int
MusicName string
Composer string
CreatedAt time.Time
UpdatedAt time.Time
}
下のコマンドで、マイグレーションファイルを生成します。
migrate create -ext sql -dir migrations -seq create_musics_table
すると、000001_create_musics_table.up.sql
と000001_create_musics_table.down.sql
が生成されます。
upは、マイグレーション実行用ファイル
downは、ロールバック(変更を元に戻す)ファイルになります。
000001_create_musics_table.up.sql
には、作成するテーブルのクエリを書きます。
CREATE TABLE IF NOT EXISTS musics (
music_id INTEGER NOT NULL PRIMARY KEY,
music_name TEXT NOT NULL,
composer TEXT NOT NULL,
createdAt TIMESTAMP NOT NULL,
updatedAt TIMESTAMP NOT NULL
);
000001_create_musics_table.down.sql
には、元に戻す時のクエリを書きます。
DROP TABLE IF EXISTS musics;
そして、先ほど書いたファイルを定義するために下のコマンドを打ちます。
migrate -path migrations -database "mysql://user:password@tcp(127.0.0.1:3306)/db?parseTime=true&charset=utf8mb4" up
下のような表示が出てきたら成功です。
migrate -path migrations -database "mysql://user:password@tcp(127.0.0.1:3306)/db?parseTime=true&charset=utf8mb4" up
1/u create_musics_table (3.981542ms)
さてここで、実際にdbの中に入って、下のクエリで変わっていたか確認します。
SHOW COLUMNS FROM musics;
下みたいになったらおkです。
+------------+-----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------+------+-----+---------+-------+
| music_id | int | NO | PRI | NULL | |
| music_name | text | NO | | NULL | |
| composer | text | NO | | NULL | |
| createdAt | timestamp | NO | | NULL | |
| updatedAt | timestamp | NO | | NULL | |
+------------+-----------+------+-----+---------+-------+
テーブルのカラム変更
テーブルに新しいカラムを加えたいとなった時には、先ほどと同じようにマイグレーションファイルを生成します。
migrate create -ext sql -dir migrations -seq rename_music_name_to_song_music
すると、000002_rename_music_name_to_song_music.up.sql
と000002_rename_music_name_to_song_music.down.sql
を生成します。
000002_rename_music_name_to_song_music.up.sql
には、テーブルを変更させるためのクエリを書きます。
ALTER TABLE musics
CHANGE COLUMN music_name song_name TEXT NOT NULL;
000002_rename_music_name_to_song_music.down.sql
には、テーブルを変更戻すためのクエリを書きます。
ALTER TABLE musics
CHANGE COLUMN song_name music_name TEXT NOT NULL;
また先ほどと同じようなコマンドを打ってマイグレーションを行います。
migrate -path migrations -database "mysql://user:password@tcp(127.0.0.1:3306)/db?parseTime=true&charset=utf8mb4" up
下のようになってたらokです。
migrate -path migrations -database "mysql://user:password@tcp(127.0.0.1:3306)/db?parseTime=true&charset=utf8mb4" up
2/u rename_music_name_to_song_music (29.513917ms)
また、同じようにdbの中に入って下のコマンドを打ちます。
SHOW COLUMNS FROM musics;
そして、今回でいうとmusic_name
がsong_name
になっていたらマイグレーションが行えています。
+-----------+-----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-----------+------+-----+---------+-------+
| music_id | int | NO | PRI | NULL | |
| song_name | text | NO | | NULL | |
| composer | text | NO | | NULL | |
| createdAt | timestamp | NO | | NULL | |
| updatedAt | timestamp | NO | | NULL | |
+-----------+-----------+------+-----+---------+-------+
ロールバックする
逆にロールバックさせて、行ったマイグレーションによる変更を元に戻すには下のコマンドを打てば完了です。
migrate -path migrations -database "mysql://user:password@tcp(127.0.0.1:3306)/db?parseTime=true&charset=utf8mb4" down 1
下のような表示になっていたら成功です。
migrate -path migrations -database "mysql://user:password@tcp(127.0.0.1:3306)/db?parseTime=true&charset=utf8mb4" down 1
2/d rename_music_name_to_song_music (16.262625ms)