今天,就要來實作 Migration 的功能!
我們選擇這一個 golang-migrate
工具來協助管資料庫版本,有興趣了解更多的朋友可以參考它的 github:https://github.com/golang-migrate/migrate?utm_source=chatgpt.com 。
然後,今天的操作流程會是:安裝 → 建立 → 執行。所有的動作都會經由 指令 生成或是程式來完成,所以不會有什麼地方是需要我們手動的。
首先,先來安裝 golang-migrate
:(適用 macOS / Linux )
brew install golang-migrate
安裝好之後,看一下版本,有成功出現版本號就表示已經安裝成功:
migrate -version
完成安裝之後,需要建立 migration 的檔案,紀錄每一次對資料庫的動作,主要會輸入以下指令,
migrate create -ext sql -dir database/migrations -seq add_description_to_tasks
指令解釋:
migrate create
:建立一個新的 migration 檔案(up
& down
)。ext sql
:指定 migration 檔案的副檔名是 .sql
。dir database/migrations
:指定檔案要存放的資料夾位置,並存在此檔案中。seq
:檔名會用「數字連號」的方式產生(000001、000002…),方便追蹤順序;如果沒有指定,預設是會用時間戳記。add_description_to_tasks
:migration 的檔案名稱,可自行命名。(範例:在 tasks 資料表中加上一個 description 欄位。)輸入之後,便會生成以下兩個檔案:
000002_add_description_to_tasks.up.sql
000002_add_description_to_tasks.down.sql
每次建立都會生成一個 up、一個 down 的檔案,分別是用來升級和回滾版本的,所以這兩個檔案對資料表做的動作是相對的!
什麼意思呢?
→ 就是如果要新增一個欄位到資料庫,那就把新增欄位的 sql 指令寫在 .up.sql
的檔案;而另一個 .down.sql
檔案就寫刪除這個欄位(表示 roll back)。
.up.sql
:(只會執行一次)
ALTER TABLE tasks ADD COLUMN description TEXT;
.down.sql
:(依照版本 roll back)
ALTER TABLE todos DROP COLUMN due_date;
完成 .up.sql
和 .down.sql
內容之後,才可以算是完成建立一個 migration 的檔案!所以每當資料庫需要更新時,就需要先透過 migration 自動生成,然後再把要做的動作寫在這兩個 sql 檔案裡面,之後再執行,資料庫才會依照你設定來跑,同時記錄版本~
最後,就是執行了! 輸入執行 migration 的指令:
migrate -database "sqlite://tasks.db" -path database/migrations up
→ 這行會執行 .up.sql
,並在 tasks
表新增 description
的欄位。
輸出:
看到這個就表示已經完成資料庫進版了!
打開資料庫看一下,就會看到已經新增了一個 description 欄位:
另外,也可以看到 Table 表多了一個 schema_migration
的選項,這張表是我們輸入 migrate
指令之後,自動在資料庫裡面建立的,用來記錄當前 migration
執行到哪一個版本。
【 在執行 migration 時的小插曲 】
雖然在一開始已經有安裝了 golang-migrate
套件,而且也安裝成功,理論上在執行時不會發生問題,不過還是發生了一點錯誤,這邊也整理給大家參考~
在一開始輸入執行指令:
migrate -database "sqlite://tasks.db" -path database/migrations up
有出現 unknown driver sqlite 的錯誤:
error: failed to open database: database driver: unknown driver sqlite (forgotten import?)
這是因為我現在所使用的 migrate binary 沒有 SQLite 支援,導致沒辦法順利使用 migration 的功能。
解決的方式有兩種:
sqlite
driver。我選擇了第二條路,哈哈哈,原因是不想再換資料庫~
以下是解決方式:
安裝有 SQLite 支援的官方的 migrate CLI:
go install -tags 'sqlite' github.com/golang-migrate/migrate/v4/cmd/migrate@latest
安裝後,可在 $GOPATH/bin
或 $HOME/go/bin
下找到 migrate
,然後把這個路徑加到 PATH:
export PATH=$PATH:$(go env GOPATH)/bin
go env GOPATH
指令找出位置 GOPATH 位置,裡面就會有 migrate
。ls $(go env GOPATH)/bin
如果有看到回傳路徑,就表示有成功。
要怎麼把 export PATH=$PATH:$(go env GOPATH)/bin
加進去?
有兩種方式可以新增:
nano ~/.zshrc
,然後再檔案的最後一行加上 export PATH=$PATH:$(go env GOPATH)/bin
。echo 'export PATH=$PATH:$(go env GOPATH)/bin' >> ~/.zshrc
新增完成之後,需要輸入以下指令,讓設定檔生效:
source ~/.zshrc
測試是否有成功?
以上設定都完成之後,就輸入:
which migrate
如果有正常顯示 migrate 的路徑,表示成功了!這時候再重新輸入 migration 的執行指令,就可以順利看到執行成功的輸出畫面。