SQL Server TVPs 批量插入数据
在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 批量插入数据的更多相关文章
- SQL Server 2008 批量插入数据时报错
前几天在SQL Server 2008同步产品数据时,总是提示二进制文本被截断的错误,但是经过检查发现数据都符合格式要求. 百思不得其解,单独插入一条条数据则可以插入,但是批量导入则报错. 批量导入代 ...
- 使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历
原文:使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历 常常遇到需要向SQL Server插入批量数据,然后在存储过程中对这些数据进行进一步处理的情况.存储过 ...
- 使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历
使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历 原文:使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历 常常遇 ...
- 使用变量向SQL Server 2008中插入数据
QT通过ODBC连接数据库SQL Server 2008,进行数据插入时遇到的问题: 先把数据存入变量中,如何使用变量进行插入?插入语句该怎么写? QSqlQuery query(db); query ...
- SQL:数据库批量插入数据
测试中有些功能要求有足够的数据进行测试,当输入字段较多时通过页面添加很慢.业务只关联单个数据库表可以通过数据库批量插入数据 批量插入数据示例: declare @i int--声明变量 --变量初始化 ...
- 从TXT文本文档向Sql Server中批量导入数据
下面我们通过以下的简单的SQL语句即可实现数据的批量导入,代码如下: Bulk insert id From 'G:\文档\test.txt' With ( fieldterminator=',', ...
- sql server中批量插入与更新两种解决方案分享
若只是需要大批量插入数据使用bcp是最好的,若同时需要插入.删除.更新建议使用SqlDataAdapter我测试过有很高的效率,一般情况下这两种就满足需求了 bcp方式 复制代码 代码如下: /// ...
- SQL Server中批量替换数据
SQL Server数据库中批量替换数据的方法 SQL Server数据库操作中,我们可能会根据某写需要去批量替换数据,那么如何批量修改替换数据呢?本文我们就介绍这一部分内容,接下来就让我们一起来了解 ...
- sql server中批量插入与更新两种解决方案分享(存储过程)
转自http://www.shangxueba.com/jingyan/1940447.html 1.游标方式 SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONG ...
随机推荐
- Vue组织架构图组件
vue-tree-chart :deciduous_tree: Vue2树形图组件 安装 npm i vue-tree-chart --save 使用 in template: <TreeC ...
- 我的第一个python web开发框架(41)——总结
我的第一个python web开发框架系列博文从17年6.7月份开始写(存了近十章稿留到9月份才开始发布),到今天结束,一年多时间,想想真不容易啊. 整个过程断断续续,中间有段时间由于工作繁忙停了好长 ...
- Ruby入坑指南
1.1 简介 Ruby语言是由松本行弘(Matz)设计,是一门通用的.面向对象的.解释型语言. 1.2 Ruby?RUBY?ruby? 1.Ruby:用来表示编程的语言 2.ruby:是指一个计算机程 ...
- 【博客导航】Nico博客导航汇总
摘要 介绍本博客关注的内容大类.任务.工具方法及链接,提供Nico博文导航. 导航汇总 [博客导航]Nico博客导航汇总 [导航]信息检索导航 [导航]Python相关 [导航]读书导航 [导航]FP ...
- JavaScript中编码函数escape,encodeURI,encodeURIComponent
第一:escape():对字符串进行编码,escape()不编码的字符:@*/+ 第二:encodeURI() 函数可把字符串作为 URI 进行编码.不会进行转义的:;/?:@&=+$,# 第 ...
- C++11のlambd表达式
在其他语言中,我们常见lambda表达式,c++11中也引入了. 利用Lambda表达式,可以方便的定义和创建匿名函数.今天,我们就来简单介绍一下C++中Lambda表达式的简单使用. 一.lambd ...
- iOS截屏并修改截图然后分享的功能实现
一. 实现的效果类似微博的截图分享 不仅截图分享的时候还进行图片的修改,增加自己的二维码 二.实现方式 苹果在ios7之后提供了一个新的通知类型:UIApplicationUserDidTakeScr ...
- Trie树(字典树)推荐文章
Trie树也被称为字典树,通过这个名字,可以明显知道这种树的结构:像字典一样进行查找的树(想想采用拼音法查找汉字的时候的过程,实质上就是一个逐字母匹配的过程).Trie树就是利用了这种思想构造出来的多 ...
- AtCoder Grand Contest 032-B - Balanced Neighbors (构造)
Time Limit: 2 sec / Memory Limit: 1024 MB Score : 700700 points Problem Statement You are given an i ...
- docker 容器的启动方式
1.Docker 优势: .更高效利用系统资源:由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高.无论是应用执行速度.内存损耗或者文件存储速度,都要比传统 ...