SQL Server 批量插入数据 方法

 

https://blog.csdn.net/heyangyi_19940703/article/details/51981731

在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题。下面介绍SQL Server支持的两种批量数据插入方法:Bulk和表值参数(Table-Valued Parameters),高效插入数据。

新建数据库:

 

 
  1. --Create DataBase

  2. create database BulkTestDB;

  3. go

  4. use BulkTestDB;

  5. go

  6. --Create Table

  7. Create table BulkTestTable(

  8. Id int primary key,

  9. UserName nvarchar(32),

  10. Pwd varchar(16))

  11. go

一.传统的INSERT方式

先看下传统的INSERT方式:一条一条的插入(性能消耗越来越大,速度越来越慢)

 

 
  1. //使用简单的Insert方法一条条插入 [慢]

  2. #region [ simpleInsert ]

  3. static void simpleInsert()

  4. {

  5. Console.WriteLine("使用简单的Insert方法一条条插入");

  6. Stopwatch sw = new Stopwatch();

  7. SqlConnection sqlconn = new SqlConnection("server=.;database=BulkTestDB;user=sa;password=123456;");

  8. SqlCommand sqlcmd = new SqlCommand();

  9. sqlcmd.CommandText = string.Format("insert into BulkTestTable(Id,UserName,Pwd)values(@p0,@p1,@p2)");

  10. sqlcmd.Parameters.Add("@p0", SqlDbType.Int);

  11. sqlcmd.Parameters.Add("@p1", SqlDbType.NVarChar);

  12. sqlcmd.Parameters.Add("@p2", SqlDbType.NVarChar);

  13. sqlcmd.CommandType = CommandType.Text;

  14. sqlcmd.Connection = sqlconn;

  15. sqlconn.Open();

  16. try

  17. {

  18. //循环插入1000条数据,每次插入100条,插入10次。

  19. for (int multiply = 0; multiply < 10; multiply++)

  20. {

  21. for (int count = multiply * 100; count < (multiply + 1) * 100; count++)

  22. {

  23.  
  24. sqlcmd.Parameters["@p0"].Value = count;

  25. sqlcmd.Parameters["@p1"].Value = string.Format("User-{0}", count * multiply);

  26. sqlcmd.Parameters["@p2"].Value = string.Format("Pwd-{0}", count * multiply);

  27. sw.Start();

  28. sqlcmd.ExecuteNonQuery();

  29. sw.Stop();

  30. }

  31. //每插入10万条数据后,显示此次插入所用时间

  32. Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));

  33. }

  34. Console.ReadKey();

  35. }

  36. catch (Exception ex)

  37. {

  38. Console.WriteLine(ex.Message);

  39. }

  40. }

  41. #endregion

循环插入1000条数据,每次插入100条,插入10次,效率是越来越慢。

二.较快速的Bulk插入方式:

使用使用Bulk插入[ 较快 ]

 

 
  1. //使用Bulk插入的情况 [ 较快 ]

  2. #region [ 使用Bulk插入的情况 ]

  3. static void BulkToDB(DataTable dt)

  4. {

  5. Stopwatch sw = new Stopwatch();

  6. SqlConnection sqlconn = new SqlConnection("server=.;database=BulkTestDB;user=sa;password=123456;");

  7. SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlconn);

  8. bulkCopy.DestinationTableName = "BulkTestTable";

  9. bulkCopy.BatchSize = dt.Rows.Count;

  10. try

  11. {

  12. sqlconn.Open();

  13. if (dt != null && dt.Rows.Count != 0)

  14. {

  15. bulkCopy.WriteToServer(dt);

  16. }

  17. }

  18. catch (Exception ex)

  19. {

  20. Console.WriteLine(ex.Message);

  21. }

  22. finally

  23. {

  24. sqlconn.Close();

  25. if (bulkCopy != null)

  26. {

  27. bulkCopy.Close();

  28. }

  29. }

  30. }

  31. static DataTable GetTableSchema()

  32. {

  33. DataTable dt = new DataTable();

  34. dt.Columns.AddRange(new DataColumn[] {

  35. new DataColumn("Id",typeof(int)),

  36. new DataColumn("UserName",typeof(string)),

  37. new DataColumn("Pwd",typeof(string))

  38. });

  39. return dt;

  40. }

  41. static void BulkInsert()

  42. {

  43. Console.WriteLine("使用简单的Bulk插入的情况");

  44. Stopwatch sw = new Stopwatch();

  45. for (int multiply = 0; multiply < 10; multiply++)

  46. {

  47. DataTable dt = GetTableSchema();

  48. for (int count = multiply * 100; count < (multiply + 1) * 100; count++)

  49. {

  50. DataRow r = dt.NewRow();

  51. r[0] = count;

  52. r[1] = string.Format("User-{0}", count * multiply);

  53. r[2] = string.Format("Pwd-{0}", count * multiply);

  54. dt.Rows.Add(r);

  55. }

  56. sw.Start();

  57. BulkToDB(dt);

  58. sw.Stop();

  59. Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));

  60. }

  61. }

  62. #endregion

循环插入1000条数据,每次插入100条,插入10次,效率快了很多。

三.使用简称TVPs插入数据

打开sqlserrver,执行以下脚本:

 

 
  1. --Create Table Valued

  2. CREATE TYPE BulkUdt AS TABLE

  3. (Id int,

  4. UserName nvarchar(32),

  5. Pwd varchar(16))

 成功后在数据库中发现多了BulkUdt的缓存表。

使用简称TVPs插入数据

 

 
  1. //使用简称TVPs插入数据 [最快]

  2. #region [ 使用简称TVPs插入数据 ]

  3. static void TbaleValuedToDB(DataTable dt)

  4. {

  5. Stopwatch sw = new Stopwatch();

  6. SqlConnection sqlconn = new SqlConnection("server=.;database=BulkTestDB;user=sa;password=123456;");

  7. const string TSqlStatement =

  8. "insert into BulkTestTable (Id,UserName,Pwd)" +

  9. " SELECT nc.Id, nc.UserName,nc.Pwd" +

  10. " FROM @NewBulkTestTvp AS nc";

  11. SqlCommand cmd = new SqlCommand(TSqlStatement, sqlconn);

  12. SqlParameter catParam = cmd.Parameters.AddWithValue("@NewBulkTestTvp", dt);

  13. catParam.SqlDbType = SqlDbType.Structured;

  14. catParam.TypeName = "dbo.BulkUdt";

  15. try

  16. {

  17. sqlconn.Open();

  18. if (dt != null && dt.Rows.Count != 0)

  19. {

  20. cmd.ExecuteNonQuery();

  21. }

  22. }

  23. catch (Exception ex)

  24. {

  25. Console.WriteLine("error>" + ex.Message);

  26. }

  27. finally

  28. {

  29. sqlconn.Close();

  30. }

  31. }

  32. static void TVPsInsert()

  33. {

  34. Console.WriteLine("使用简称TVPs插入数据");

  35. Stopwatch sw = new Stopwatch();

  36. for (int multiply = 0; multiply < 10; multiply++)

  37. {

  38. DataTable dt = GetTableSchema();

  39. for (int count = multiply * 100; count < (multiply + 1) * 100; count++)

  40. {

  41. DataRow r = dt.NewRow();

  42. r[0] = count;

  43. r[1] = string.Format("User-{0}", count * multiply);

  44. r[2] = string.Format("Pwd-{0}", count * multiply);

  45. dt.Rows.Add(r);

  46. }

  47. sw.Start();

  48. TbaleValuedToDB(dt);

  49. sw.Stop();

  50. Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));

  51. }

  52. Console.ReadLine();

  53. }

  54. #endregion

循环插入1000条数据,每次插入100条,插入10次,效率是越来越慢,后面测试,将每次插入的数据量增大,会更大的体现TPVS插入的效率。

 

转载参考至TJVictor专栏:http://blog.csdn.net/tjvictor/archive/2009/07/18/4360030.aspx

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值