傳統做法逐筆 INSERT 或拼接 SQL 字串,不僅效能低落,還易受 SQL 注入攻擊。.NET Framework 內建的 System.Data.SqlClient.SqlBulkCopy 類別,專為大量資料高效匯入 SQL Server 設計,速度極快且程式碼簡潔。
using System;
using System.Data;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Data.SqlClient;
namespace WindowsApplication2
{
public partial class Form1 : Form
{
public Form1() { InitializeComponent(); }
private void button1_Click(object sender, EventArgs e)
{
string connString = "server=localhost;uid=sa;pwd=sqlgis;database=master";
OpenFileDialog fd = new OpenFileDialog();
if (fd.ShowDialog() == DialogResult.OK)
{
TransferData(fd.FileName, "sheet1", connString);
}
}
public void TransferData(string excelFile, string sheetName, string connectionString)
{
DataSet ds = new DataSet();
try
{
// 1. 讀取 Excel 資料
string strConn = $"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={excelFile};Extended Properties=Excel 8.0;";
using (OleDbConnection conn = new OleDbConnection(strConn))
{
conn.Open();
string strExcel = $"select * from [{sheetName}$]";
OleDbDataAdapter myCommand = new OleDbDataAdapter(strExcel, strConn);
myCommand.Fill(ds, sheetName);
}
// 2. 若目標表不存在則建立(簡易版,實務建議預先建立結構)
string strSql = $"if object_id('{sheetName}') is null create table {sheetName}(";
foreach (DataColumn c in ds.Tables[0].Columns)
{
strSql += $"[{c.ColumnName}] varchar(255),";
}
strSql = strSql.TrimEnd(',') + ")";
using (SqlConnection sqlconn = new SqlConnection(connectionString))
{
sqlconn.Open();
SqlCommand command = sqlconn.CreateCommand();
command.CommandText = strSql;
command.ExecuteNonQuery();
}
// 3. 使用 SqlBulkCopy 批量匯入
using (SqlBulkCopy bcp = new SqlBulkCopy(connectionString))
{
bcp.SqlRowsCopied += bcp_SqlRowsCopied;
bcp.BatchSize = 100; // 每批筆數
bcp.NotifyAfter = 100; // 進度通知間隔
bcp.DestinationTableName = sheetName;
bcp.WriteToServer(ds.Tables[0]);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// 進度顯示
void bcp_SqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
{
this.Text = e.RowsCopied.ToString();
this.Update();
}
}
}
SqlRowsCopied 事件的間隔筆數,配合 UI 更新進度。測試環境:開發機、6 萬筆資料、單一工作表。
結果:含讀取 Excel 總耗時約 10 秒,純 SqlBulkCopy 匯入僅 4.5 秒。相較逐筆 INSERT 可提升數十倍效能。
SqlBulkCopyOptions.TableLock 鎖定資料表以加速匯入(需獨佔存取)。SqlBulkCopy 是 C# 大量寫入 SQL Server 的最佳利器。掌握其用法,能輕鬆應對百萬級資料匯入需求,大幅縮短 ETL 處理時間。