在資料庫版本升級、環境遷移、開發/測試/生產同步場景中,需將表結構、索引、觸發器、預存程序、檢視表、預設值、規則、使用者定義型別等物件完整複製。SQL Server 提供 SQL-DMO (SQL 2000) / SMO (SQL 2005+) 物件模型中的 Transfer 類別,支援程式化控制複製行為。本文詳細說明核心屬性、方法與使用模式。
| 屬性名稱 | 型別 | 說明 | 預設值 |
|---|---|---|---|
| CopyAllObjects | Boolean | 複製所有物件類型 (表/檢視/SP/觸發/UDF/UDT/規則/預設/索引) | False |
| CopyAllTables | Boolean | 複製所有資料表 | False |
| CopyAllViews | Boolean | 複製所有檢視表 | False |
| CopyAllStoredProcedures | Boolean | 複製所有預存程序 | False |
| CopyAllTriggers | Boolean | 複製所有觸發器 | False |
| CopyAllDefaults | Boolean | 複製所有預設值約束 | False |
| CopyAllRules | Boolean | 複製所有規則約束 | False |
| CopyAllUserDefinedDatatypes | Boolean | 複製所有使用者定義資料型別 | False |
| CopyData | Boolean | 同時複製資料列 (僅適用表) | False |
| DropDestObjectsFirst | Boolean | 複製前先刪除目標端同名物件 | False |
| IncludeDependencies | Boolean | 自動包含相依物件 (如檢視表依賴的表) | True |
| ScriptType | Enum | 腳本類型: Create/Drop/CreateDrop | Create |
| DestServer/DestDatabase/DestLogin/DestPassword/DestUseTrustedConnection | String | 目標伺服器連線資訊 | - |
AddObject(ByVal Object As Object):加入單一物件 (需先取得物件參考)AddObjectByName(ByVal Name As String, ByVal Type As ObjectType):依名稱加入物件ScriptTransfer():生成腳本字串 (不執行,供審查/存檔)TransferData():直接執行複製至目標資料庫using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
var sourceConn = new ServerConnection("SourceServer", "login", "pwd");
var sourceSrv = new Server(sourceConn);
var sourceDb = sourceSrv.Databases["SourceDB"];
var destConn = new ServerConnection("DestServer", "login", "pwd");
var destSrv = new Server(destConn);
var destDb = destSrv.Databases["DestDB"]; // 需預先建立
var transfer = new Transfer(sourceDb)
{
CopyAllTables = true,
CopyAllViews = true,
CopyAllStoredProcedures = true,
CopyAllTriggers = true,
CopyAllDefaults = true,
CopyAllRules = true,
CopyAllUserDefinedDatatypes = true,
CopyData = false, // 只複製結構
DropDestObjectsFirst = true,
IncludeDependencies = true,
DestinationServer = destSrv.Name,
DestinationDatabase = destDb.Name,
DestinationLogin = "login",
DestinationPassword = "pwd",
DestinationLoginSecure = false
};
// 選項 1: 直接執行複製
transfer.TransferData();
// 選項 2: 生成腳本審查後再執行
var script = transfer.ScriptTransfer();
// File.WriteAllText("SyncSchema.sql", script);
// 然後在目標端執行 script
Import-Module SqlServer
$src = New-Object Microsoft.SqlServer.Management.Smo.Server("SourceServer")
$srcDb = $src.Databases["SourceDB"]
$dest = New-Object Microsoft.SqlServer.Management.Smo.Server("DestServer")
$destDb = $dest.Databases["DestDB"]
$transfer = New-Object Microsoft.SqlServer.Management.Smo.Transfer($srcDb)
$transfer.CopyAllObjects = $true
$transfer.CopyData = $false
$transfer.DropDestObjectsFirst = $true
$transfer.DestinationServer = $dest.Name
$transfer.DestinationDatabase = $destDb.Name
$transfer.DestinationLogin = "login"
$transfer.DestinationPassword = "pwd"
# 生成腳本檔
$script = $transfer.ScriptTransfer()
$script | Out-File "C:\Deploy\SyncSchema_$(Get-Date -Format yyyyMMdd).sql" -Encoding UTF8
# 或直接執行
# $transfer.TransferData()
CopyAllObjects=$false,改用 AddObjectByName 精確控制FILESTREAM, COLUMNSTORE) 會報錯,需預先相容性檢查TransferData 單執行緒、無進度、易逾時。生產建議:生成腳本 → 分批執行 → 並行索引建立 → 驗證行數GRANT/DENY、ALTER AUTHORIZATIONWITH ENCRYPTION 的 SP/檢視/觸發器無法腳本化,需解密或排除| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| SMO Transfer | 程式化控制、支援腳本生成、.NET/PowerShell 原生 | 大型資料庫慢、單執行緒、權限不同步 | 中小型資料庫自動化部署、CI/CD 管線 |
| SSIS 移轉資料庫任務 | GUI 設定、支援資料移動、平行處理 | 難以版控、除錯困難、元件較重 | 一次性大遷移、非開發人員操作 |
| SQLPackage / DACPAC | 狀態式部署、增量同步、版控友好、支援預部署/部署後腳本 | 學習曲線、僅 Schema (資料需 BCP/Bulk Insert) | DevOps、資料庫專案 (SSDT)、持續部署 |
| Redgate SQL Compare / Flyway / Liquibase | 專業比對、報告豐富、支援遷移腳本版本化 | 商業授權成本 | 企業級資料庫變更管理 |
Transfer 物件是快速原型、腳本生成、中小型環境同步的利器。但對於 **生產級持續交付**,強烈建議採用 **SSDT (SQL Server Data Tools) + DACPAC + SQLPackage** 的狀態式部署模式,將 Schema 視為程式碼納入 Git 版控,實現真正的 Database DevOps。