2026年10月28日 星期三

使用SQL Database Projects與GitHub Actions打造Azure SQL資料庫CI/CD流水線

 

作者:楊先民  
精誠資訊/恆逸教育訓練中心資深講師


※網路引用請註明完整出處


前言

在傳統的資料庫維護模式中,開發團隊通常依賴開發人員手寫 ALTER TABLE 或 CREATE PROCEDURE 等 T-SQL 變更指令碼(Migration Scripts),再由資料庫管理者(DBA)或部署人員手動對生產環境資料庫執行。

然而,手動執行的隱患極高:指令碼執行順序錯誤、環境遺漏變更、缺乏版本控制,甚至人為疏失都可能導致線上系統崩潰。為了解決這個痛點,現代化資料庫開發導入了「以狀態為基礎(State-based)」的資料庫專案模式,配合 CI/CD 流水線(Continuous Integration / Continuous Deployment),讓資料庫架構變更如同應用程式程式碼一樣,實現版本控制、自動建置驗證與無縫部署。

本文將基於 Microsoft 官方實戰教學,詳細剖析如何透過 SQL Database Projects(SDK 樣式 .sqlproj) 與 GitHub Actions,為 Azure SQL Database 打造一套現代化的 CI/CD 流程。


一、 架構核心概念:Declarative vs. Imperative

在進入操作流程前,必須先理解 SQL Database Projects 的核心哲學:宣告式(Declarative / State-based)開發。

1.       傳統變更模式(Imperative / Migration-based): 開發者撰寫「如何變更」的步驟(如:ALTER TABLE Add Column X),逐一按順序執行。缺點是必須精準管理每個指令碼的版控與順序。

2.       資料庫專案模式(Declarative / State-based): 開發者只宣告「目標狀態(Desired State)」(如:專案中的 .sql 檔定義資料表最終該長什麼樣子)。當編譯專案時,會產出一個 .dacpac 檔案(Data-tier Application Package,資料層應用程式封裝檔)。部署工具(SqlPackage 或 GitHub Actions)會自動比較 .dacpac 與目標資料庫當前的架構差異,並自動生成最適切的 CREATE / ALTER / DROP 指令碼來達成一致。


二、 前置準備與環境建置

要順利執行本實驗的流水線,需要準備以下基礎設施與開發工具:

1. 雲端資源準備

·         Azure SQL Database:作為部署的目標資料庫。在 Azure Portal 中建立一個資料庫(例:AdventureWorksLT),並選用 Serverless 無伺服器運算層(或開發測試層)。

·         防火牆與安全性設定:

o    在 Azure SQL Server 的防火牆設定中,將 「允許 Azure 服務和資源存取此伺服器」(Allow Azure services and resources to access this server) 開啟為 Yes。這是為了讓 GitHub Actions 執行階段的 Runner 能夠遠端存取資料庫。

o    選擇適當的驗證方式:可選用 SQL 身份驗證(SQL Authentication,設定 Admin 帳號密碼)或 Microsoft Entra ID 驗證。

2. 本機開發環境配置

本機需安裝以下工具:

·          Git 與 GitHub CLI (gh):處理程式碼版本控制與 GitHub 資源管理。

·         .NET 8.0 SDK (或更新版本):提供跨平台編譯環境。

·         Visual Studio Code:搭配 MSSQL Extension(內建 SQL Database Projects 支援)。


環境建置的第一步,是在本機安裝 .NET 的 SQL 專案範本:

dotnet new install Microsoft.Build.Sql.Templates

此命令會安裝 SDK 樣式的 sqlproj 範本(Microsoft.Build.Sql),讓資料庫專案可以使用跨平台的 dotnet build 命令進行編譯,不再侷限於傳統 Windows 平台的 MSBuild。


三、 建立與本機編譯 SQL Database Project

1.
初始化資料庫專案

建立專案目錄並使用 .NET CLI 初始化 SQL 專案:

mkdir AdventureWorksDB

cd AdventureWorksDB

dotnet new sqlproj -tp SqlAzureV12


關鍵參數說明:
-tp SqlAzureV12 指定目標平台(Target Platform)為 Azure SQL Database。若未指定,預設會使用 SQL Server 本地版本,可能導致發行至 Azure 時發生功能不相容的錯誤。

初始化後會生成 AdventureWorksDB.sqlproj 檔案。SDK 樣式專案具備「預設萬用字元比對(Globbing)」特性,代表目錄下所有的 .sql 檔案都會自動被列入編譯,無須在 .sqlproj 中手動逐一清冊。

2. 加入資料庫物件 (Schema Definition)

在專案目錄下分類建立資料庫物件的 DDL 指令碼:

建立資料表檔 Tables/InventoryLog.sql:

SQL

CREATE TABLE [dbo].[InventoryLog] (

    [LogID] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,

    [ProductID] INT NOT NULL,

    [ChangeDate] DATETIME2 NOT NULL DEFAULT GETDATE(),

    [QuantityChange] INT NOT NULL,

    [ChangeType] NVARCHAR(20) NOT NULL

);


建立預存程序檔
StoredProcedures/uspLogInventoryChange.sql:

SQL

CREATE PROCEDURE [dbo].[uspLogInventoryChange]

    @ProductID INT,

    @QuantityChange INT,

    @ChangeType NVARCHAR(20)

AS

BEGIN

    INSERT INTO [dbo].[InventoryLog] (ProductID, QuantityChange, ChangeType)

    VALUES (@ProductID, @QuantityChange, @ChangeType);

END;


3.
本機編譯驗證

在提交版控前,先於本機執行編譯:

dotnet build


編譯成功後,會在 bin/Debug/ 目錄下生成 AdventureWorksDB.dacpac。這個 .dacpac 包含整個資料庫模型架構,也是後續 CI/CD 流水線的核心交付物(Artifact)。


四、 版本控管與 GitHub 儲存庫綁定

完成本機建置後,透過 Git 與 GitHub CLI 將專案推送到遠端儲存庫(Repository):

初始化 Git 並進行首次提交:

git init

git add .

git commit -m "Initial commit - SQL Database Project"


使用 GitHub CLI 建立 GitHub Repository 並推送:

gh repo create AdventureWorksDB --public --source=. --remote=origin --push


此時,資料庫專案已成功備份並託管至 GitHub。


五、 設定 GitHub Secrets 安全憑證

為了讓 GitHub Actions 自動化工作流程能夠登入並部署至 Azure SQL Database,絕對不能將密碼直接硬碼(Hardcode)在 YAML 寫死。我們必須在 GitHub 儲存庫設定敏感資訊(Secrets):

進入 GitHub Repository → Settings → Secrets and variables → Actions,新增以下兩個 Secrets:

1.   DB_SERVER:Azure SQL Server 的完整功能變數名稱(例如:sqlserver-demo.database.windows.net)。

2.   DB_PASSWORD:Azure SQL Server 管理員帳號的密碼。

(註:若採用 Microsoft Entra ID 服務主體,則需設定 Azure Service Principal 的 Client ID、Tenant ID 與 Client Secret)。


六、 打造 GitHub Actions CI/CD 流水線

在專案根目錄下建立 .github/workflows/deploy-db.yml 檔案,定義整個 CI/CD Pipeline 的自動化流程。

一套健全的 SQL CI/CD 流水線通常分為兩個階段(Jobs):

1.Build Job(持續整合 CI):負責檢查 T-SQL 語法、編譯 .sqlproj 並生成 .dacpac 成品。

2.Deploy Job(持續部署 CD):下載 .dacpac 成品,並呼叫部署 Action 部署至 Azure SQL Database。


完整 Workflow YAML 配置範例:

YAML

name: Deploy SQL Database Project

 

on:

  push:

    branches:

      - main

  workflow_dispatch:

 

jobs:

  build:

    runs-on: ubuntu-latest

    steps:

      - name: Checkout repository

        uses: actions/checkout@v4

 

      - name: Setup .NET SDK

        uses: actions/setup-dotnet@v4

        with:

          dotnet-version: '8.0.x'

 

      - name: Build SQL Project

        run: dotnet build AdventureWorksDB.sqlproj -c Release

 

      - name: Upload DACPAC Artifact

        uses: actions/upload-artifact@v4

        with:

          name: dacpac

          path: bin/Release/*.dacpac

 

  deploy:

    needs: build

    runs-on: ubuntu-latest

    steps:

      - name: Download DACPAC Artifact

        uses: actions/download-artifact@v4

        with:

          name: dacpac

 

      - name: Deploy DACPAC to Azure SQL Database

        uses: azure/sql-action@v2.2

        with:

          connection-string: 'Server=tcp:${{ secrets.DB_SERVER }},1433;Initial Catalog=AdventureWorksLT;Persist Security Info=False;User ID=sqladmin;Password=${{ secrets.DB_PASSWORD }};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;'

          path: './AdventureWorksDB.dacpac'

          action: 'publish'


七、 CI/CD 自動化運作與驗證測試

當我們將 .github/workflows/deploy-db.yml 提交並推送到 GitHub 的 main 分支時,GitHub Actions 便會自動啟動!

1. 流水線執行解析

· Build 階段: Runner 會拉取最新程式碼,安裝 .NET 8 SDK,執行 dotnet build -c Release。如果 T-SQL 存在語法錯誤或引用了不存在的資料表,編譯將直接宣告失敗,達到 早期發現錯誤(Fail Fast) 的效果。成功後會將 .dacpac 暫存至 Artifact。

· Deploy 階段: deploy 工作等待 build 完成後,拉取 .dacpac,並透過官方的 azure/sql-action 連結至 Azure SQL Database。SqlPackage 引擎會精確比對目標資料庫現況,發現資料庫目前缺少 [dbo].[InventoryLog] 資料表與 [dbo].[uspLogInventoryChange] 預存程序,自動生成對應的 CREATE 敘述句並完成發行。

2. 驗證變更與持續疊代測試

為驗證 CI/CD 流水線的動態回應能力,我們可以進行二次變更測試:

1.修改架構:在本機專案的 Tables/InventoryLog.sql 資料表中加入一個新欄位,例如 [CreatedBy] NVARCHAR(50) NULL。

2.提交程式碼:

git add .

git commit -m "Add CreatedBy column to InventoryLog"

git push origin main

1.觀察 GitHub Actions:推送後,GitHub Actions 再次觸發。

2.檢查 Azure SQL Database:部署完成後,使用 SSMS 或 VS Code MSSQL 工具查詢 Azure SQL,會發現 InventoryLog 資料表已成功新增了 CreatedBy 欄位,且原本的資料(若有)依然完好無損!這就是 SqlPackage 在宣告式發行時自動維護資料完整性的強大之處。


八、 總結與最佳實踐建議

透過本次 Microsoft Labs 的演練,我們成功實現了資料庫架構的版控化與自動化部署。這套 SQL CI/CD 流水線帶來了以下核心優勢:

1.單一事實來源(Single Source of Truth):Git 儲存庫即為資料庫架構的權威來源,避免正式環境與開發環境架構不一致(Schema Drift)。

2.降低部署風險:告別人工手動執行腳本,完全交由 automated pipeline 比對與發行,大大減少人為遺漏或順序錯誤的風險。

3.企業級擴充建議:

· 多環境部署(Multi-environment Support):可擴充 YAML,加入 GitHub Environments 機制。先部署至 Staging(測試環境),經由審核(Protection Rules)後再自動部署至 Production(正式環境)。

· 安全性防護:正式生產環境建議搭配 Azure Key Vault 或 OpenID Connect (OIDC) 進行無金鑰(Keyless)認證,進一步提升雲端資安等級。

掌握 SQL Database Projects 與 CI/CD 技術,是將現代化 Agile 與 DevOps 理念擴展至資料庫層級的必經之路。

0 意見:

張貼留言