SQL Server 批量插入数据的两种方法
在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题。下面介绍 SQL Server支持的两种批量数据插入方法:Bulk和表值参数(Table-Valued Parameters)。
运行下面的脚本,建立测试数据库和表值参数。
- --Create DataBase
- create database BulkTestDB;
- go
- use BulkTestDB;
- go
- --Create Table
- Create table BulkTestTable(
- Id int primary key,
- UserName nvarchar(32),
- Pwd varchar(16))
- go
- --Create Table Valued
- CREATE TYPE BulkUdt AS TABLE
- (Id int,
- UserName nvarchar(32),
- Pwd varchar(16))
下面我们使用最简单的Insert语句来插入100万条数据,代码如下:
- Stopwatch sw = new Stopwatch();
- SqlConnection sqlConn = new SqlConnection(
- ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);//连接数据库
- SqlCommand sqlComm = new SqlCommand();
- sqlComm.CommandText = string.Format("insert into BulkTestTable(Id,UserName,Pwd)values(@p0,@p1,@p2)");//参数化SQL
- sqlComm.Parameters.Add("@p0", SqlDbType.Int);
- sqlComm.Parameters.Add("@p1", SqlDbType.NVarChar);
- sqlComm.Parameters.Add("@p2", SqlDbType.VarChar);
- sqlComm.CommandType = CommandType.Text;
- sqlComm.Connection = sqlConn;
- sqlConn.Open();
- try
- {
- //循环插入100万条数据,每次插入10万条,插入10次。
- for (int multiply = 0; multiply < 10; multiply++)
- {
- for (int count = multiply * 100000; count < (multiply + 1) * 100000; count++)
- {
- sqlComm.Parameters["@p0"].Value = count;
- sqlComm.Parameters["@p1"].Value = string.Format("User-{0}", count * multiply);
- sqlComm.Parameters["@p2"].Value = string.Format("Pwd-{0}", count * multiply);
- sw.Start();
- sqlComm.ExecuteNonQuery();
- sw.Stop();
- }
- //每插入10万条数据后,显示此次插入所用时间
- Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
- }
- }
- catch (Exception ex)
- {
- throw ex;
- }
- finally
- {
- sqlConn.Close();
- }
- Console.ReadLine();
耗时图如下:

由于运行过慢,才插入10万条就耗时72390 milliseconds,所以我就手动强行停止了。
下面看一下使用Bulk插入的情况:
bulk方法主要思想是通过在客户端把数据都缓存在Table中,然后利用SqlBulkCopy一次性把Table中的数据插入到数据库
代码如下:
- public static void BulkToDB(DataTable dt)
- {
- SqlConnection sqlConn = new SqlConnection(
- ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);
- SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConn);
- bulkCopy.DestinationTableName = "BulkTestTable";
- bulkCopy.BatchSize = dt.Rows.Count;
- try
- {
- sqlConn.Open();
- if (dt != null && dt.Rows.Count != 0)
- bulkCopy.WriteToServer(dt);
- }
- catch (Exception ex)
- {
- throw ex;
- }
- finally
- {
- sqlConn.Close();
- if (bulkCopy != null)
- bulkCopy.Close();
- }
- }
- public static DataTable GetTableSchema()
- {
- DataTable dt = new DataTable();
- dt.Columns.AddRange(new DataColumn[]{
- new DataColumn("Id",typeof(int)),
- new DataColumn("UserName",typeof(string)),
- new DataColumn("Pwd",typeof(string))});
- return dt;
- }
- static void Main(string[] args)
- {
- Stopwatch sw = new Stopwatch();
- for (int multiply = 0; multiply < 10; multiply++)
- {
- DataTable dt = Bulk.GetTableSchema();
- for (int count = multiply * 100000; count < (multiply + 1) * 100000; count++)
- {
- DataRow r = dt.NewRow();
- r[0] = count;
- r[1] = string.Format("User-{0}", count * multiply);
- r[2] = string.Format("Pwd-{0}", count * multiply);
- dt.Rows.Add(r);
- }
- sw.Start();
- Bulk.BulkToDB(dt);
- sw.Stop();
- Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
- }
- Console.ReadLine();
- }
耗时图如下:

可见,使用Bulk后,效率和性能明显上升。使用Insert插入10万数据耗时72390,而现在使用Bulk插入100万数据才耗时17583。
最后再看看使用表值参数的效率,会另你大为惊讶的。
表值参数是SQL Server 2008新特性,简称TVPs。对于表值参数不熟悉的朋友,可以参考最新的book online,我也会另外写一篇关于表值参数的博客,不过此次不对表值参数的概念做过多的介绍。言归正传,看代码:
- public static void TableValuedToDB(DataTable dt)
- {
- SqlConnection sqlConn = new SqlConnection(
- ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);
- const string TSqlStatement =
- "insert into BulkTestTable (Id,UserName,Pwd)" +
- " SELECT nc.Id, nc.UserName,nc.Pwd" +
- " FROM @NewBulkTestTvp AS nc";
- SqlCommand cmd = new SqlCommand(TSqlStatement, sqlConn);
- SqlParameter catParam = cmd.Parameters.AddWithValue("@NewBulkTestTvp", dt);
- catParam.SqlDbType = SqlDbType.Structured;
- //表值参数的名字叫BulkUdt,在上面的建立测试环境的SQL中有。
- catParam.TypeName = "dbo.BulkUdt";
- try
- {
- sqlConn.Open();
- if (dt != null && dt.Rows.Count != 0)
- {
- cmd.ExecuteNonQuery();
- }
- }
- catch (Exception ex)
- {
- throw ex;
- }
- finally
- {
- sqlConn.Close();
- }
- }
- public static DataTable GetTableSchema()
- {
- DataTable dt = new DataTable();
- dt.Columns.AddRange(new DataColumn[]{
- new DataColumn("Id",typeof(int)),
- new DataColumn("UserName",typeof(string)),
- new DataColumn("Pwd",typeof(string))});
- return dt;
- }
- static void Main(string[] args)
- {
- Stopwatch sw = new Stopwatch();
- for (int multiply = 0; multiply < 10; multiply++)
- {
- DataTable dt = TableValued.GetTableSchema();
- for (int count = multiply * 100000; count < (multiply + 1) * 100000; count++)
- {
- DataRow r = dt.NewRow();
- r[0] = count;
- r[1] = string.Format("User-{0}", count * multiply);
- r[2] = string.Format("Pwd-{0}", count * multiply);
- dt.Rows.Add(r);
- }
- sw.Start();
- TableValued.TableValuedToDB(dt);
- sw.Stop();
- Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
- }
- Console.ReadLine();
- }
耗时图如下:

比Bulk还快5秒。
SQL Server 批量插入数据的两种方法的更多相关文章
- SQL Server 批量插入数据的两种方法(转)
此文原创自CSDN TJVictor专栏:http://blog.csdn.net/tjvictor/archive/2009/07/18/4360030.aspx 在SQL Server 中插入一条 ...
- 转:SQL Server 批量插入数据的两种方法
在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍SQL Server支持的两种批量 ...
- SQLServer 批量插入数据的两种方法
SQLServer 批量插入数据的两种方法-发布:dxy 字体:[增加 减小] 类型:转载 在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Ins ...
- SQL 2005批量插入数据的二种方法
SQL 2005批量插入数据的二种方法 Posted on 2010-07-22 18:13 moss_tan_jun 阅读(2635) 评论(2) 编辑 收藏 在SQL Server 中插入一条数据 ...
- SQL Server 批量插入数据方案 SqlBulkCopy 的简单封装,让批量插入更方便
一.Sql Server插入方案介绍 关于 SqlServer 批量插入的方式,有三种比较常用的插入方式,Insert.BatchInsert.SqlBulkCopy,下面我们对比以下三种方案的速度 ...
- MyBatis 批量插入数据的 3 种方法!
批量插入功能是我们日常工作中比较常见的业务功能之一,之前我也写过一篇关于<MyBatis Plus 批量数据插入功能,yyds!>的文章,但评论区的反馈不是很好,主要有两个问题:第一,对 ...
- MySQL批量插入数据的几种方法
最近公司要求测试数据库的性能,就上网查了一些批量插入数据的代码,发现有好几种不同的用法,插入同样数据的耗时也有区别 别的先不说,先上一段代码与君共享 方法一: package com.bigdata; ...
- SQL Server中迁移数据的几种方法
1.通过工具"DTS"的设计器进行导入或者导出 DTS的设计器功能强大,支持多任务,也是可视化界面,容易操作,但知道的人一般不 多,如果只是进行SQL Server数据库中部分表的 ...
- SQL Server 批量插入数据的方法
运行下面的脚本,建立测试数据库和表. --Create DataBase create database BulkTestDB; go use BulkTestDB; go --Create Tabl ...
随机推荐
- SQL函数——LENGTH()和LENGTHB()
LENGTH()函数是比较简单同时也是非常有用的一个函数,在此小记一下,加深印象以备后用! 1:先上实验的例子——我新建了一张Student表,插入了若干条测试数据,如下图所示: 2:实验LENGTH ...
- LINQ标准查询操作符详解(转)
一. 关于LINQ LINQ 英文全称是“Language-Integrated Query”,中文为“语言集成查询”,它是微软首席架构师.Delphi 之父和C# 之父——Anders ...
- PAT1013
#include<cstdio>#include<cstring>#include<vector>using namespace std;const int max ...
- WP8_读写XML
/// <summary> /// WP手机,XML读写类 /// </summary> public class WPXmlRW { /// <summary> ...
- JS常用的设计模式(12)—— 迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该方法中的内部表示. js中我们经常会封装一个each函数用来实现迭代器. array的迭代器: forEach = functio ...
- Spring web Flow2学习笔记
想抽时间研究一下Spring web Flow2,能够找到的唯一电子书是<深入解析Spring+MVC与Web Flow>,我现在摘录本书的一段内容如下,通过这一段,大家可以想象中文背景的 ...
- 自己实现的一款在线Javascript正则表达式测试器——JRE-Parser
本文最初发布于我的个人博客:http://jerryzou.com/posts/jreparser/ 昨天在看<正则表达式30分钟入门教程>的时候,看到博主自己实现了一个C#写的正则测试器 ...
- JavaScript API 设计原则
网+线下沙龙 | 移动APP模式创新:给你一个做APP的理由>> 好的 API 设计:在自描述的同时,达到抽象的目标. 设计良好的 API ,开发者可以快速上手,没必要经常抱着手册和文档, ...
- linux禁止tty终端登陆
修改文件/etc/pam.d/system-auth #%PAM-1.0# This file is auto-generated.# User changes will be destroyed t ...
- 《第一行代码--Android》阅读笔记之界面设计
1.单位dp.dip.sp.pt.px.in.mm 这里引用StackOverFlow上的一个解答: px is one pixel. sp is scale-independent pixels. ...