適用場景
- ERP 類國產軟體(K/3、U8 等)帳套損壞無法修復
- 新建同結構帳套,需將舊資料導入新帳套
- DTS 導入導出不夠靈活,需精細控制導入順序、約束處理
核心邏輯:存儲程序 sp_ExportDatabase
CREATE PROCEDURE [sp_ExportDatabase]
@SourceDB VARCHAR(100) -- 來源資料庫名稱
AS
BEGIN
SET NOCOUNT ON;
-- 1. 禁用所有約束與觸發器(避免外鍵阻擋、觸發器副作用)
-- 2. 清空目標表資料
-- 3. 動態建構欄位清單(排除計算欄、timestamp 等)
-- 4. 處理 IDENTITY 欄位:SET IDENTITY_INSERT ON/OFF
-- 5. 執行 INSERT ... SELECT 跨庫複製
-- 6. 重新啟用約束與觸發器
END
關鍵技術細節
1. 游標遍歷使用者表
DECLARE Ctb CURSOR FOR
SELECT name, id FROM sysobjects
WHERE xtype = 'U'
AND name IN (/* 可指定表清單,跳過損壞表 */)
ORDER BY name;
2. 三階段處理流程
| 階段 | 操作 | 目的 |
| Phase 1 |
DISABLE TRIGGER ALL + NOCHECK CONSTRAINT ALL |
移除寫入阻礙 |
| Phase 2 |
DELETE 目標表 → 動態建構 INSERT ... SELECT |
資料遷移核心 |
| Phase 3 |
ENABLE TRIGGER ALL + CHECK CONSTRAINT ALL |
恢復資料完整性 |
3. IDENTITY 欄位特殊處理
IF EXISTS (SELECT * FROM syscolumns WHERE id = @tid AND status = 0x80)
BEGIN
-- 0x80 表示 IDENTITY 欄位
SET @sql = 'SET IDENTITY_INSERT ' + @Utb + ' ON ' + @sql;
EXEC(@sql);
EXEC('SET IDENTITY_INSERT ' + @Utb + ' OFF');
END
4. 計算欄與 timestamp 自動排除
DECLARE Clu CURSOR FOR
SELECT name FROM syscolumns
WHERE id = @tid
AND iscomputed = 0
AND xtype <> 189; -- 189 = timestamp
使用方式
- 在目標(新)資料庫建立此存儲程序
- 執行:
EXEC sp_ExportDatabase 'SourceDB_Name'
- 觀察訊息輸出確認各表導入狀態
優缺點分析
| 優點 | 缺點/風險 |
| 完全掌控導入順序與邏輯 |
需理解來源/目標結構差異 |
| 可跳過損壞表繼續導入 |
大量資料執行時間較長 |
| 自動處理 IDENTITY/計算欄 |
跨版本結構差異需手動調整 |
| 無需額外工具,純 T-SQL |
不支援資料轉換/清洗邏輯 |
現代化建議
- SQL Server 2005+ 可改用
MERGE 實現 UPSERT 邏輯
- SSIS 套件提供視覺化、可重用、可參數化的更佳替代
- 大型遷移建議:唯讀備份 + 記錄檔傳送 或 AlwaysOn 可用性群組 同步後再切換
此腳本展示了「動態 SQL + 游標 + 系統表元資料」的經典組合,理解其原理有助於掌握資料庫元編程技術。