C#批量插入數(shù)據(jù)到sqlserver的方法詳解
方法一:逐條插入,性能最差,不推薦使用
INSERT INTO Test(Id, Name) VALUES(newid(), '1'); INSERT INTO Test(Id, Name) VALUES(newid(), '2');
C#方法
static void InsertOne()
{
Console.WriteLine("采用一條一條插入的方式實(shí)現(xiàn)");
Stopwatch sw = new Stopwatch();
using (SqlConnection conn = new SqlConnection(StrConnMsg)) //using中會自動(dòng)Open和Close 連接。
{
string sql = "INSERT INTO Test(Id,Name) VALUES(newid(),@p)";
conn.Open();
for (int i = 0; i < totalRow; i++)
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@p", i);
sw.Start();
cmd.ExecuteNonQuery();
Console.WriteLine(string.Format("插入一條記錄,已耗時(shí){0}毫秒", sw.ElapsedMilliseconds));
}
if (i == getRow)
{
sw.Stop();
break;
}
}
}
Console.WriteLine(string.Format("插入{0}條記錄,每{4}條的插入時(shí)間是{1}毫秒,預(yù)估總得插入時(shí)間是{2}毫秒,{3}分鐘", totalRow, sw.ElapsedMilliseconds, ((sw.ElapsedMilliseconds / getRow) * totalRow), GetMinute((sw.ElapsedMilliseconds / getRow * totalRow)), getRow));
}
static int GetMinute(long l)
{
return (Int32)l / 60000;
}
結(jié)論
插入100w條記錄,預(yù)計(jì)需要50分鐘時(shí)間,每插入一條記錄大概需要3毫秒左右。
方法二:拼接sql
INSERT INTO Test(Id, Name) VALUES(newid(), '1'),(newid(), '2')
C#方法
static void InsertFour()
{
Console.WriteLine("采用拼接批量SQL插入的方式實(shí)現(xiàn)");
Stopwatch sw = new Stopwatch();
using (SqlConnection conn = new SqlConnection(StrConnMsg)) //using中會自動(dòng)Open和Close 連接。
{
conn.Open();
sw.Start();
for (int j = 0; j < totalRow / getRow;j++ )
{
StringBuilder sb = new StringBuilder();
sb.Append("INSERT INTO Product(Id,Name,Price) VALUES");
using (SqlCommand cmd = new SqlCommand())
{
for (int i = 0; i < getRow; i++)
{
sb.AppendFormat("(newid(),'{0}'),", i);
}
cmd.Connection = conn;
cmd.CommandText = sb.ToString().TrimEnd(',');
cmd.ExecuteNonQuery();
}
}
sw.Stop();
Console.WriteLine(string.Format("插入{0}條記錄,共耗時(shí){1}毫秒",totalRow,sw.ElapsedMilliseconds));
}
}
結(jié)論
插入100w條記錄,預(yù)計(jì)需要10分鐘時(shí)間
方法三:使用Bulk
BULK INSERT
[ database_name . [ schema_name ] . | schema_name . ] [ table_name | view_name ]
FROM 'data_file'
[ WITH
(
[ [ , ] BATCHSIZE = batch_size ] --BATCHSIZE指令來設(shè)置在單個(gè)事務(wù)中可以插入到表中的記錄的數(shù)量
[ [ , ] CHECK_CONSTRAINTS ] --指定在大容量導(dǎo)入操作期間,必須檢查所有對目標(biāo)表或視圖的約束。若沒有 CHECK_CONSTRAINTS 選項(xiàng),則所有 CHECK 和 FOREIGN KEY 約束都將被忽略,并且在此操作之后表的約束將標(biāo)記為不可信。
[ [ , ] CODEPAGE = { 'ACP' | 'OEM' | 'RAW' | 'code_page' } ] --指定該數(shù)據(jù)文件中數(shù)據(jù)的代碼頁
[ [ , ] DATAFILETYPE =
{ 'char' | 'native'| 'widechar' | 'widenative' } ] --指定 BULK INSERT 使用指定的數(shù)據(jù)文件類型值執(zhí)行導(dǎo)入操作。
[ [ , ] FIELDTERMINATOR = 'field_terminator' ] --標(biāo)識分隔內(nèi)容的符號
[ [ , ] FIRSTROW = first_row ] --指定要加載的第一行的行號。默認(rèn)值是指定數(shù)據(jù)文件中的第一行
[ [ , ] FIRE_TRIGGERS ] --是否啟動(dòng)觸發(fā)器
[ [ , ] FORMATFILE = 'format_file_path' ]
[ [ , ] KEEPIDENTITY ] --指定導(dǎo)入數(shù)據(jù)文件中的標(biāo)識值用于標(biāo)識列
[ [ , ] KEEPNULLS ] --指定在大容量導(dǎo)入操作期間空列應(yīng)保留一個(gè)空值,而不插入用于列的任何默認(rèn)值
[ [ , ] KILOBYTES_PER_BATCH = kilobytes_per_batch ]
[ [ , ] LASTROW = last_row ] --指定要加載的最后一行的行號
[ [ , ] MAXERRORS = max_errors ] --指定允許在數(shù)據(jù)中出現(xiàn)的最多語法錯(cuò)誤數(shù),超過該數(shù)量后將取消大容量導(dǎo)入操作。
[ [ , ] ORDER ( { column [ ASC | DESC ] } [ ,...n ] ) ] --指定數(shù)據(jù)文件中的數(shù)據(jù)如何排序
[ [ , ] ROWS_PER_BATCH = rows_per_batch ]
[ [ , ] ROWTERMINATOR = 'row_terminator' ] --標(biāo)識分隔行的符號
[ [ , ] TABLOCK ] --指定為大容量導(dǎo)入操作持續(xù)時(shí)間獲取一個(gè)表級鎖
[ [ , ] ERRORFILE = 'file_name' ] --指定用于收集格式有誤且不能轉(zhuǎn)換為 OLE DB 行集的行的文件。
)]
C#方法
static void InsertTwo()
{
Console.WriteLine("使用Bulk插入的實(shí)現(xiàn)方式");
Stopwatch sw = new Stopwatch();
DataTable dt = GetTableSchema();
using (SqlConnection conn = new SqlConnection(StrConnMsg))
{
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn);
bulkCopy.DestinationTableName = "Product";
bulkCopy.BatchSize = dt.Rows.Count;
conn.Open();
sw.Start();
for (int i = 0; i < totalRow;i++ )
{
DataRow dr = dt.NewRow();
dr[0] = Guid.NewGuid();
dr[1] = string.Format("商品", i);
dr[2] = (decimal)i;
dt.Rows.Add(dr);
}
if (dt != null && dt.Rows.Count != 0)
{
bulkCopy.WriteToServer(dt);
sw.Stop();
}
Console.WriteLine(string.Format("插入{0}條記錄共花費(fèi){1}毫秒,{2}分鐘", totalRow, sw.ElapsedMilliseconds, GetMinute(sw.ElapsedMilliseconds)));
}
}
static DataTable GetTableSchema()
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] {
new DataColumn("Id",typeof(Guid)),
new DataColumn("Name",typeof(string))
});
return dt;
}
結(jié)論
插入100w條記錄,預(yù)計(jì)需要8s多
方法四:使用TVPs插入數(shù)據(jù)
創(chuàng)建緩存表
--Create Table Valued CREATE TYPE TestTemp AS TABLE (Id int, Name nvarchar(32))
c#方法
static void TbaleValuedToDB(DataTable dt)
{
Stopwatch sw = new Stopwatch();
SqlConnection sqlconn = new SqlConnection("server=.;database=TestDB;user=sa;password=123456;");
const string TSqlStatement =
"insert into Test (Id,Name)" +
" SELECT tt.Id, tt.Name" +
" FROM @TestTvp AS tt";
SqlCommand cmd = new SqlCommand(TSqlStatement, sqlconn);
SqlParameter catParam = cmd.Parameters.AddWithValue("@TestTvp", dt);
catParam.SqlDbType = SqlDbType.Structured;
catParam.TypeName = "dbo.TestTemp";
try
{
sqlconn.Open();
if (dt != null && dt.Rows.Count != 0)
{
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
Console.WriteLine("error>" + ex.Message);
}
finally
{
sqlconn.Close();
}
}
static void TVPsInsert()
{
Console.WriteLine("使用簡稱TVPs插入數(shù)據(jù)");
Stopwatch sw = new Stopwatch();
for (int i = 0; i < 10; i++)
{
DataTable dt = GetTableSchema();
for (int j = i * 100; j < (i + 1) * 100; j++)
{
DataRow r = dt.NewRow();
r[0] = j;
r[1] = string.Format("{0}", i * j);
dt.Rows.Add(r);
}
sw.Start();
TbaleValuedToDB(dt);
sw.Stop();
Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
}
Console.ReadLine();
}
結(jié)論
插入100w條記錄,預(yù)計(jì)需要11s多
以上就是C#批量插入數(shù)據(jù)到sqlserver的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于C#插入數(shù)據(jù)到sqlserver的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解如何利用C#實(shí)現(xiàn)設(shè)置系統(tǒng)時(shí)間
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)設(shè)置系統(tǒng)時(shí)間功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12
利用C#版OpenCV實(shí)現(xiàn)圓心求取實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于如何利用C#版OpenCV實(shí)現(xiàn)圓心求取的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
C# 實(shí)現(xiàn)ADSL自動(dòng)斷網(wǎng)和撥號的方法(適用于撥號用戶)
下面小編就為大家?guī)硪黄狢# 實(shí)現(xiàn)ADSL自動(dòng)斷網(wǎng)和撥號的方法(適用于撥號用戶)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12
C# 獲取某個(gè)時(shí)間的0點(diǎn)0分和23點(diǎn)59分59秒
這篇文章主要介紹了C# 獲取某個(gè)時(shí)間的0點(diǎn)0分和23點(diǎn)59分59秒,文中給大家提到了java 獲取某一日期的0點(diǎn)0分0秒和23點(diǎn)59分59秒,需要的朋友可以參考下2019-09-09
Unity報(bào)錯(cuò)InvalidOperationException: out of sync的解決
今天在做個(gè)東西,發(fā)現(xiàn)報(bào)錯(cuò),特此來記錄一下,本文介紹了Unity報(bào)錯(cuò)InvalidOperationException: out of sync的解決,感興趣的可以了解一下2021-05-05
詳解C# parallel中并行計(jì)算的四種寫法總結(jié)
在C#中,parallel關(guān)鍵字可以用于并行計(jì)算。本文為大家總結(jié)了四種C# parallel并行計(jì)算的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-11-11

