專案上線、系統遷移、異構同步、歷史資料歸檔——大量資料匯入是 DBA 與實施顧問的高頻任務。選錯方法會導致匯入耗時數倍、記錄檔暴增、鎖死線上業務。
SELECT * INTO TargetDB.dbo.NewTable
FROM SourceDB.dbo.SourceTable;
INSERT INTO TargetDB.dbo.TargetTable (col1, col2, ...)
SELECT col1, col2, ... FROM SourceDB.dbo.SourceTable;
WHERE id > @last_id ORDER BY id OFFSET 0 ROWS FETCH NEXT 50000 ROWS ONLY 迴圈。WITH (TABLOCK) + 簡單/大量記錄復原模式 → 最小記錄。OPENROWSET 直接讀取:SELECT * INTO TargetTable
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0;Database=D:\Data\Source.xlsx;HDR=YES', 'SELECT * FROM [Sheet1$]');
| 優點 | 缺點 |
|---|---|
| 視覺化清洗直觀、支援複雜業務規則 | 人工介入、難以自動化排程、Excel 104 萬列上限 |
| 異構來源通用 | 大檔案開啟慢、記憶體壓力大 |
-- 匯出
bcp "SELECT * FROM SourceDB.dbo.SourceTable" queryout D:\Data\Source.dat -S . -T -c -t, -r\n
-- 匯入(需目標表存在)
bcp TargetDB.dbo.TargetTable in D:\Data\Source.dat -S . -T -c -t, -r\n -b 50000 -h "TABLOCK, CHECK_CONSTRAINTS"
-b 批次大小(建議 50,000~100,000);-h TABLOCK 最小記錄;-c 字元模式通用。BULK INSERT TargetDB.dbo.TargetTable
FROM 'D:\Data\Source.dat'
WITH (
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
BATCHSIZE = 50000,
TABLOCK,
CHECK_CONSTRAINTS,
FIRSTROW = 2, -- 跳過標題列
CODEPAGE = '65001' -- UTF-8
);
INSERT INTO TargetTable (col1, col2, ...)
SELECT col1, col2, ...
FROM OPENROWSET(BULK 'D:\Data\Source.dat',
FORMATFILE = 'D:\Data\Source.fmt',
FIRSTROW = 2) AS src;
格式檔 (`.fmt`) 可定義欄位對應、型別轉換、跳過欄位,支援複雜 ETL。
| 維度 | T-SQL SELECT/INSERT | BCP/BULK INSERT | SSIS | Excel/CSV 中繼 |
|---|---|---|---|---|
| 資料量 | < 100 萬列 | 100 萬 ~ 億級 | 億級+ / 複雜轉換 | < 50 萬列 / 需人工 |
| 異構支援 | 僅 SQL Server | 需文字檔中繼 | 原生支援所有 ADO.NET/OLE DB | 通用 |
| 自動化排程 | Agent 作業 | Agent / CMD 排程 | SSISDB / Agent | 困難 |
| 記錄檔影響 | 大(完整模式) | 可最小記錄 | 可最小記錄 | 視匯入方式 |
| 開發維護成本 | 低 | 中 | 高 | 低(一次性) |
ONLINE = ON)。TABLOCK 達到最小記錄。BATCHSIZE 避免單一交易過大(建議 50k~100k)。