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("采用一條一條插入的方式實現(xiàn)"); Stopwatch sw = new Stopwatch(); using (SqlConnection conn = new SqlConnection(StrConnMsg)) //using中會自動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("插入一條記錄,已耗時{0}毫秒", sw.ElapsedMilliseconds)); } if (i == getRow) { sw.Stop(); break; } } } Console.WriteLine(string.Format("插入{0}條記錄,每{4}條的插入時間是{1}毫秒,預(yù)估總得插入時間是{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ù)計需要50分鐘時間,每插入一條記錄大概需要3毫秒左右。
方法二:拼接sql
INSERT INTO Test(Id, Name) VALUES(newid(), '1'),(newid(), '2')
C#方法
static void InsertFour() { Console.WriteLine("采用拼接批量SQL插入的方式實現(xiàn)"); Stopwatch sw = new Stopwatch(); using (SqlConnection conn = new SqlConnection(StrConnMsg)) //using中會自動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}條記錄,共耗時{1}毫秒",totalRow,sw.ElapsedMilliseconds)); } }
結(jié)論
插入100w條記錄,預(yù)計需要10分鐘時間
方法三:使用Bulk
BULK INSERT [ database_name . [ schema_name ] . | schema_name . ] [ table_name | view_name ] FROM 'data_file' [ WITH ( [ [ , ] BATCHSIZE = batch_size ] --BATCHSIZE指令來設(shè)置在單個事務(wù)中可以插入到表中的記錄的數(shù)量 [ [ , ] CHECK_CONSTRAINTS ] --指定在大容量導(dǎo)入操作期間,必須檢查所有對目標(biāo)表或視圖的約束。若沒有 CHECK_CONSTRAINTS 選項,則所有 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 ] --指定要加載的第一行的行號。默認值是指定數(shù)據(jù)文件中的第一行 [ [ , ] FIRE_TRIGGERS ] --是否啟動觸發(fā)器 [ [ , ] FORMATFILE = 'format_file_path' ] [ [ , ] KEEPIDENTITY ] --指定導(dǎo)入數(shù)據(jù)文件中的標(biāo)識值用于標(biāo)識列 [ [ , ] KEEPNULLS ] --指定在大容量導(dǎo)入操作期間空列應(yīng)保留一個空值,而不插入用于列的任何默認值 [ [ , ] KILOBYTES_PER_BATCH = kilobytes_per_batch ] [ [ , ] LASTROW = last_row ] --指定要加載的最后一行的行號 [ [ , ] MAXERRORS = max_errors ] --指定允許在數(shù)據(jù)中出現(xiàn)的最多語法錯誤數(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ù)時間獲取一個表級鎖 [ [ , ] ERRORFILE = 'file_name' ] --指定用于收集格式有誤且不能轉(zhuǎn)換為 OLE DB 行集的行的文件。 )]
C#方法
static void InsertTwo() { Console.WriteLine("使用Bulk插入的實現(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}條記錄共花費{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ù)計需要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ù)計需要11s多
以上就是C#批量插入數(shù)據(jù)到sqlserver的方法詳解的詳細內(nèi)容,更多關(guān)于C#插入數(shù)據(jù)到sqlserver的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#編程實現(xiàn)Excel文檔中搜索文本內(nèi)容的方法及思路
有了在Word文檔中編程實現(xiàn)搜索文本的經(jīng)驗,在Excel中實現(xiàn)這個功能也并非難事。2013-07-07C#使用SqlBulkCopy批量復(fù)制數(shù)據(jù)到數(shù)據(jù)表
這篇文章主要介紹了C#使用SqlBulkCopy批量復(fù)制數(shù)據(jù)到數(shù)據(jù)表的方法,較為詳細的講述了SqlBulkCopy批量復(fù)制數(shù)據(jù)到數(shù)據(jù)表的原理與實現(xiàn)技巧,需要的朋友可以參考下2014-10-10詳解WPF如何在基礎(chǔ)控件上顯示Loading等待動畫
這篇文章主要為大家詳細介紹了WPF如何在基礎(chǔ)控件上顯示Loading等待動畫的效果,文中的示例代碼講解詳細,具有一定的學(xué)習(xí)價值,需要的可以參考一下2023-04-04