在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

一.传统的INSERT方式

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

        //使用简单的Insert方法一条条插入 [慢]
#region [ simpleInsert ]
static void simpleInsert()
{
Console.WriteLine("使用简单的Insert方法一条条插入");
Stopwatch sw = new Stopwatch();
SqlConnection sqlconn = new SqlConnection("server=.;database=BulkTestDB;user=sa;password=123456;");
SqlCommand sqlcmd = new SqlCommand();
sqlcmd.CommandText = string.Format("insert into BulkTestTable(Id,UserName,Pwd)values(@p0,@p1,@p2)");
sqlcmd.Parameters.Add("@p0", SqlDbType.Int);
sqlcmd.Parameters.Add("@p1", SqlDbType.NVarChar);
sqlcmd.Parameters.Add("@p2", SqlDbType.NVarChar);
sqlcmd.CommandType = CommandType.Text;
sqlcmd.Connection = sqlconn;
sqlconn.Open();
try
{
//循环插入1000条数据,每次插入100条,插入10次。
for (int multiply = ; multiply < ; multiply++)
{
for (int count = multiply * ; count < (multiply + ) * ; count++)
{ sqlcmd.Parameters["@p0"].Value = count;
sqlcmd.Parameters["@p1"].Value = string.Format("User-{0}", count * multiply);
sqlcmd.Parameters["@p2"].Value = string.Format("Pwd-{0}", count * multiply);
sw.Start();
sqlcmd.ExecuteNonQuery();
sw.Stop();
}
//每插入10万条数据后,显示此次插入所用时间
Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
}
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
#endregion

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

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

使用使用Bulk插入[ 较快 ]

        //使用Bulk插入的情况 [ 较快 ]
#region [ 使用Bulk插入的情况 ]
static void BulkToDB(DataTable dt)
{
Stopwatch sw = new Stopwatch();
SqlConnection sqlconn = new SqlConnection("server=.;database=BulkTestDB;user=sa;password=123456;");
SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlconn);
bulkCopy.DestinationTableName = "BulkTestTable";
bulkCopy.BatchSize = dt.Rows.Count;
try
{
sqlconn.Open();
if (dt != null && dt.Rows.Count != )
{
bulkCopy.WriteToServer(dt);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
sqlconn.Close();
if (bulkCopy != null)
{
bulkCopy.Close();
}
}
}
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 BulkInsert()
{
Console.WriteLine("使用简单的Bulk插入的情况");
Stopwatch sw = new Stopwatch();
for (int multiply = ; multiply < ; multiply++)
{
DataTable dt = GetTableSchema();
for (int count = multiply * ; count < (multiply + ) * ; count++)
{
DataRow r = dt.NewRow();
r[] = count;
r[] = string.Format("User-{0}", count * multiply);
r[] = string.Format("Pwd-{0}", count * multiply);
dt.Rows.Add(r);
}
sw.Start();
BulkToDB(dt);
sw.Stop();
Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
}
}
#endregion

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

三.使用简称TVPs插入数据

打开sqlserrver,执行以下脚本:

--Create Table Valued
CREATE TYPE BulkUdt AS TABLE
(Id int,
UserName nvarchar(32),
Pwd varchar(16)
)

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

使用简称TVPs插入数据

        //使用简称TVPs插入数据 [最快]
#region [ 使用简称TVPs插入数据 ]
static void TbaleValuedToDB(DataTable dt)
{
Stopwatch sw = new Stopwatch();
SqlConnection sqlconn = new SqlConnection("server=.;database=BulkTestDB;user=sa;password=123456;");
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;
catParam.TypeName = "dbo.BulkUdt";
try
{
sqlconn.Open();
if (dt != null && dt.Rows.Count != )
{
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
Console.WriteLine("error>" + ex.Message);
}
finally
{
sqlconn.Close();
}
}
static void TVPsInsert()
{
Console.WriteLine("使用简称TVPs插入数据");
Stopwatch sw = new Stopwatch();
for (int multiply = ; multiply < ; multiply++)
{
DataTable dt = GetTableSchema();
for (int count = multiply * ; count < (multiply + ) * ; count++)
{
DataRow r = dt.NewRow();
r[] = count;
r[] = string.Format("User-{0}", count * multiply);
r[] = string.Format("Pwd-{0}", count * multiply);
dt.Rows.Add(r);
}
sw.Start();
TbaleValuedToDB(dt);
sw.Stop();
Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
}
Console.ReadLine();
}
#endregion

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

PS:

使用新特性TVPs插入100w数据 只需2秒,实例如下:

 --创建表
CREATE TABLE BulkCategorySubscriber
(
[category_id] [int] NOT NULL,
[subscriber_id] [int] NOT NULL,
[added_date] [datetime] NOT NULL DEFAULT (getdate())
) --创建 type
--Create Table Valued
CREATE TYPE BulkCategorySubscriberType AS TABLE
(
[category_id] [int] NOT NULL,
[subscriber_id] [int] NOT NULL,
[added_date] [datetime] NOT NULL DEFAULT (getdate())
)

--1、定于 dbo.BulkCategorySubscriberType 类型变量
declare @data dbo.BulkCategorySubscriberType --2、将100w数据插入到@data中
insert into @data(category_id,subscriber_id,added_date)
select top 1000000 category_id,subscriber_id,added_date from NewsLetterSystem_CategorySubscriber --3、最后将@data中数据插入到目标数据表中
insert into BulkCategorySubscriber (category_id,subscriber_id,added_date)
select category_id,subscriber_id,added_date from @data

SQL Server TVPs 批量插入数据的更多相关文章

  1. SQL Server 2008 批量插入数据时报错

    前几天在SQL Server 2008同步产品数据时,总是提示二进制文本被截断的错误,但是经过检查发现数据都符合格式要求. 百思不得其解,单独插入一条条数据则可以插入,但是批量导入则报错. 批量导入代 ...

  2. 使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历

    原文:使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历 常常遇到需要向SQL Server插入批量数据,然后在存储过程中对这些数据进行进一步处理的情况.存储过 ...

  3. 使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历

    使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历   原文:使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历 常常遇 ...

  4. 使用变量向SQL Server 2008中插入数据

    QT通过ODBC连接数据库SQL Server 2008,进行数据插入时遇到的问题: 先把数据存入变量中,如何使用变量进行插入?插入语句该怎么写? QSqlQuery query(db); query ...

  5. SQL:数据库批量插入数据

    测试中有些功能要求有足够的数据进行测试,当输入字段较多时通过页面添加很慢.业务只关联单个数据库表可以通过数据库批量插入数据 批量插入数据示例: declare @i int--声明变量 --变量初始化 ...

  6. 从TXT文本文档向Sql Server中批量导入数据

    下面我们通过以下的简单的SQL语句即可实现数据的批量导入,代码如下: Bulk insert id From 'G:\文档\test.txt' With ( fieldterminator=',', ...

  7. sql server中批量插入与更新两种解决方案分享

    若只是需要大批量插入数据使用bcp是最好的,若同时需要插入.删除.更新建议使用SqlDataAdapter我测试过有很高的效率,一般情况下这两种就满足需求了 bcp方式 复制代码 代码如下: /// ...

  8. SQL Server中批量替换数据

    SQL Server数据库中批量替换数据的方法 SQL Server数据库操作中,我们可能会根据某写需要去批量替换数据,那么如何批量修改替换数据呢?本文我们就介绍这一部分内容,接下来就让我们一起来了解 ...

  9. sql server中批量插入与更新两种解决方案分享(存储过程)

    转自http://www.shangxueba.com/jingyan/1940447.html 1.游标方式 SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONG ...

随机推荐

  1. windows下为qt msvc版本配置调试器

    原文:https://blog.csdn.net/whatnamecaniuse/article/details/80716616 根据开发机的环境,下载 我的机器是win10,因此下载win 10 ...

  2. oracle 基础查询语句

    select abs(10) from dual; --取绝对值select ceil(3.6) from dual;--向上取整 select power(2,3) from dual;--2的3次 ...

  3. Selenium 4即将发布:每个QA都应该知道的

    阅读原文 Simon Stewart(Selenium的创始成员)在班加罗尔的Selenium大会议上正式确认了Selenium4.0的发布日期和一些主要更新.我们先来提前了解一下Selenium 4 ...

  4. java多线程编程之连续打印abc的几种解法

    一道编程题如下: 实例化三个线程,一个线程打印a,一个线程打印b,一个线程打印c,三个线程同时执行,要求打印出10个连着的abc. 题目分析: 通过题意我们可以得出,本题需要我们使用三个线程,三个线程 ...

  5. BAT面试题:使用数组实现一个简单的阻塞队列

    这道题是我亲身经历的一道大厂面试题,非常值得分享! 这道题可以分为两个步骤进行编码解答,第一步是基于数组实现一个队列,第二步是实现线程阻塞. 如果是基于数组实现栈的数据结构,那么我们只需要一个指针进行 ...

  6. 利用ELK分析Nginx日志生产实战(高清多图)

    本文以api.mingongge.com.cn域名为测试对象进行统计,日志为crm.mingongge.com.cn和risk.mingongge.com.cn请求之和(此二者域名不具生产换环境统计意 ...

  7. 原创|1分钟搞定 Nginx 版本的平滑升级与回滚

    Nginx无论是对于运维.开发.还是测试来说,都是日常工作需要掌握的一个知识点,之前也写过不少关于Nginx相关的文章: Nginx服务介绍与安装 Nginx服务配置文件介绍 Nginx配置虚拟主机 ...

  8. Vue—组件传值及vuex的使用

    一.父子组件之间的传值 1.父组件向子组件传值: 子组件在props中创建一个属性,用以接收父组件传来的值 父组件中注册子组件 在子组件标签中添加子组件props中创建的属性 把需要传给子组件的值赋给 ...

  9. 注意:QQ影音视频压缩时长丢失

    客户宣传片发来,高清的,比较大,500多M,需要转成小一点的,放在客户网站上,于是用QQ影音转码压缩下,变成低质量的.如下 一切都很顺利,提示进度100%! 这一切都是电脑自动的,又是提示成功的,千想 ...

  10. 【tool】VLC播放rtmp协议

    您的输入无法被打开: VLC 无法打开 MRL「rtmp://112.35.3.71:47201/api/6276-0.1546939632724.flv」.详情请检查日志.