SqlServer批量插入(SqlBulkCopy、表值参数)
创建了一个用来测试的Student表:
CREATE TABLE [dbo].[Student](
[ID] [int] PRIMARY KEY NOT NULL,
[Num] [varchar](10) NULL,
[Name] [nvarchar](64) NULL,
[Age] [int] NULL
)
一、SqlBulkCopy类:使用数据库BCP协议进行数据的批量复制,每一批的数量大约800条。
/// <summary>
/// 批量插入SqlBulkCopy
/// </summary>
/// <param name="dt"></param>
/// <param name="tableName">表名</param>
public static void BatchInsertBySqlBulkCopy(DataTable dt, string tableName)
{
using (SqlBulkCopy sbc = new SqlBulkCopy(connString))
{
sbc.BatchSize = dt.Rows.Count;
sbc.BulkCopyTimeout = ;
sbc.DestinationTableName = tableName;
for (int i = ; i < dt.Columns.Count; i++)
{
sbc.ColumnMappings.Add(dt.Columns[i].ColumnName, i);
}
//全部写入数据库
sbc.WriteToServer(dt);
}
}
5万条数据插入花了2秒的时间:
二、表值参数:也叫表变量参数,使用用户定义的表类型来声明,简单理解就是可以把一个表当做参数传递。
CREATE TYPE [dbo].[mytb_student] AS TABLE(
[ID] [int] NOT NULL,
[Num] [varchar](10) NULL,
[Name] [nvarchar](64) NULL,
[Age] [int] NULL
)
/// <summary>
/// 批量插入使用表值参数
/// </summary>
/// <param name="dt"></param>
public static void BatchInsertByTableValue(DataTable dt, string sqlText)
{
using (SqlConnection sqlConn = new SqlConnection(connString))
{
using (SqlCommand sqlCmd = new SqlCommand(sqlText, sqlConn))
{
//把DataTable当做参数传入
SqlParameter sqlPar = sqlCmd.Parameters.AddWithValue("@dt", dt);
//指定表值参数中包含的构造数据的特殊数据类型。
sqlPar.SqlDbType = SqlDbType.Structured;
sqlPar.TypeName = "dbo.mytb_student";//表值参数名称
sqlConn.Open();
sqlCmd.ExecuteNonQuery();
}
}
}
同样插入5万条数据,也是花了2秒的时间。
总结:SqlServer数据库批量插入除了使用SqlBulkCopy和表值参数,还可以使用SqlDataAdapter的Update方法,经过本人测试,在数据量越大的情况下,使用SqlBulkCopy的性能是最好的。
三、在SqlBulkCopy和表值参数进行批量插入时,DataTable列的赋值顺序必须和DB中的表类型定义的字段顺序一致。
IF NOT EXISTS(SELECT * FROM sys.table_types WHERE name = 'type_im_check_detail' AND is_user_defined = 1)
BEGIN
CREATE TYPE type_im_check_detail AS TABLE
(
-- 字段定义顺序
[sheet_no] [varchar](18) NOT NULL,
[item_no] [varchar](40) NOT NULL,
check_date DATETIME null,
in_price NUMERIC(16,4) null,
sale_price NUMERIC(16,4) null,
real_qty NUMERIC(16,4) null,
recheck_qty NUMERIC(16,4) null,
memo NVARCHAR(100) NULL,
item_barcode VARCHAR(40) null,
row_id NUMERIC(16,4) null,
produce_date DATETIME null,
valid_date DATETIME null,
stock_qty NUMERIC(16,4) null
)
END
GO IF NOT EXISTS(SELECT * FROM sys.table_types WHERE name = 'type_im_sheet_barcode_qty' AND is_user_defined = 1)
BEGIN
CREATE TYPE type_im_sheet_barcode_qty AS TABLE
(
-- 字段定义顺序
trans_no VARCHAR(2) NOT NULL,
[sheet_no] [varchar](18) NOT NULL,
line_no INT NOT NULL,
[item_no] [varchar](30) NOT NULL,
item_barcode VARCHAR(38) NOT NULL,
qty NUMERIC(16,4) NULL,
qty2 NUMERIC(16,4) NULL,
qty3 NUMERIC(16,4) NULL
)
END
GO IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID('pr_insert_im_check_detail') AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
BEGIN
DROP PROCEDURE dbo.pr_insert_im_check_detail
END
GO
CREATE PROCEDURE dbo.pr_insert_im_check_detail
(
@detail type_im_check_detail READONLY,
@barcodeDetail type_im_sheet_barcode_qty READONLY
)
AS
BEGIN
SET XACT_ABORT ON
BEGIN TRANSACTION INSERT t_im_check_detail (sheet_no, item_no, check_date, in_price, sale_price, real_qty, recheck_qty, memo, item_barcode, row_id, produce_date, valid_date,stock_qty)
SELECT sheet_no,item_no,check_date,in_price,sale_price,real_qty,recheck_qty,memo,item_barcode,row_id,produce_date,valid_date,stock_qty
FROM @detail INSERT t_im_sheet_barcode_qty (trans_no,sheet_no, item_no,line_no,item_barcode, qty)
SELECT trans_no,sheet_no, item_no,line_no,item_barcode, qty
FROM @barcodeDetail COMMIT TRANSACTION
SET XACT_ABORT OFF
END
GO
// DataTable列定义顺序
private DataTable GetNewDetailTable()
{
DataTable dt = new DataTable();
dt.Columns.Add("sheet_no");
dt.Columns.Add("item_no");
dt.Columns.Add("check_date");
dt.Columns.Add("in_price");
dt.Columns.Add("sale_price");
dt.Columns.Add("real_qty");
dt.Columns.Add("recheck_qty");
dt.Columns.Add("memo");
dt.Columns.Add("item_barcode");
dt.Columns.Add("row_id");
dt.Columns.Add("produce_date");
dt.Columns.Add("valid_date");
dt.Columns.Add("stock_qty"); return dt;
} private DataTable GetNewBarcodeDetailTable()
{
DataTable dt = new DataTable();
dt.Columns.Add("trans_no");
dt.Columns.Add("sheet_no");
dt.Columns.Add("line_no");
dt.Columns.Add("item_no");
dt.Columns.Add("item_barcode");
dt.Columns.Add("qty");
dt.Columns.Add("qty2");
dt.Columns.Add("qty3"); return dt;
}
#region init table
DataTable dt = GetNewDetailTable();
foreach (var item in details)
{
// datatable赋值顺序
DataRow row = dt.NewRow();
row["sheet_no"] = item.sheet_no;
row["item_no"] = item.item_no;
row["check_date"] = item.check_date;
row["in_price"] = item.in_price;
row["sale_price"] = item.sale_price;
row["real_qty"] = item.real_qty;
row["recheck_qty"] = item.recheck_qty;
row["memo"] = item.memo;
row["item_barcode"] = item.item_barcode;
row["row_id"] = item.row_id;
row["produce_date"] = item.produce_date;
row["valid_date"] = item.valid_date;
row["stock_qty"] = item.stock_qty; dt.Rows.Add(row);
} var dtBarcode = GetNewBarcodeDetailTable();
foreach (var item in barcodeDetail)
{
//datatable列赋值顺序
DataRow row = dtBarcode.NewRow();
row["trans_no"] = "CR";
row["sheet_no"] = item.sheet_no;
row["line_no"] = ;
row["item_no"] = item.item_no;
row["item_barcode"] = item.item_barcode;
row["qty"] = item.qty;
row["qty2"] = 0.00;
row["qty3"] = 0.00; dtBarcode.Rows.Add(row);
}
#endregion SqlParameter[] paras = new SqlParameter[] {
new SqlParameter("@detail", SqlDbType.Structured) { Value = dt, TypeName = "type_im_check_detail" },
new SqlParameter("@barcodeDetail", SqlDbType.Structured) { Value = dtBarcode, TypeName = "type_im_sheet_barcode_qty" }
};
Repository.Database.ExecuteSqlCommand("pr_insert_im_check_detail @detail,@barcodeDetail", paras);
**********转载:https://blog.csdn.net/chwenbin/article/details/79112570
SqlServer批量插入(SqlBulkCopy、表值参数)的更多相关文章
- SQLServer 批量插入数据的两种方法
SQLServer 批量插入数据的两种方法-发布:dxy 字体:[增加 减小] 类型:转载 在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Ins ...
- sqlserver数据库批量插入-SqlBulkCopy
当想在数据库中插入大量数据时,使用insert 不仅效率低,而且会导致一系列的数据库性能问题 当使用insert语句进行插入数据时.我使用了两种方式: 每次插入数据时,都只插入一条数据库,这个会导致每 ...
- Mybatis 针对ORACLE和MYSQL的批量插入与多参数批量删除
今天利用Mybatis的<for each>标签做oracle的批量插入数据时,发现和MySQL数据库有区别.在此记录下,以防之后再踩坑. 一.批量插入: 1.controller: /* ...
- SqlServer——批量插入数据
像Major表里面批量插入数据演示: 代码如下: Declare @I int Set @I= Begin Tran InsertData: Insert into Major values(@I,' ...
- Mybatis 插入与批量插入以及多参数批量删除
实体类: import java.io.Serializable; public class AttachmentTable implements Serializable { private sta ...
- sqlserver批量插入数据问题
下午做一个批量添加的功能,自动添加的那种,总是没有达到理想情况,后来请教师傅,给了这个批量添加的代码,一改果然好了,敬佩之情油然而生哈.分享下~ insert into t_ShopApplicati ...
- 批量插入 SqlBulkCopy的测试
关于SqlBulkCopy的测试 最近要做.net关于sql大量插入,找到了sqlbulkcopy(自己google下,应该很多说明了)这个好东西,于是测试下性能,用了三个方法对比: 1)直接用ado ...
- 简单的sqlserver批量插入数据easy batch insert data use loop function in sqlserver
--example 1: DECLARE @pid INT,@name NVARCHAR(50),@level INT,@i INT,@column2 INT SET @pid=0 SET @name ...
- C# 数据库批量插入数据之 —— SqlBulkCopy、表值参数
创建了一个用来测试的Student表: CREATE TABLE [dbo].[Student]( [ID] [int] PRIMARY KEY NOT NULL, ) NULL, ) NULL, [ ...
随机推荐
- 查询sqlserver数据库视图、存储过程等包含特定的字符串
SELECT A.name , B.definition FROM SYS.objects A INNER JOIN sys.sql_modules B ON A.object_id = B.obje ...
- java定时任务调度工具Timer与Quartz的区别
Timer与Quartz的区别有三点: 1.出身不同:Timer由jdk直接提供,调用方式简单粗暴,不需要其它jar包支持.Quartz并非jdk自带,需要引入相应的jar包 2.能力区别:主要体现在 ...
- 201671010127 2016—2017-2 通过一个小程序对Java的再认识。
学习了将近四周的Java语言,对于Java语言,我也有了更进一步的理解,出于对Java语言的喜爱,我总是喜欢没事的时候,自己敲一些很简单的代码,一边学习Java语言,一边对比C语言,往往可以帮助我们更 ...
- const与指针的纠缠
当使用带有const的指针时其实有两种意思.一种指的是你不能修改指针本身的内容,另一种指的是你不能修改指针指向的内容. 先说指向const的指针,它的意思是指针指向的内容是不能被修改的.它有两种写法. ...
- 19-字符串匹配(kmp || substr,find)
链接:https://www.nowcoder.com/acm/contest/77/C来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 面试题:servlet jsp cook session 背1
一.Servlet是什么?JSP是什么?它们的联系与区别是什么? Servlet是Java编写的运行在Servlet容器的服务端程序,狭义的Servlet是指Servlet接口,广义的Servlet是 ...
- c# 获取客户端ip、mac、机器名、操作系统、浏览器信息
d using System; using System.Collections.Generic; using System.Linq; using System.Web; using System. ...
- PCL 编程多个点云合成
博客转载自:https://blog.csdn.net/sunboyiris/article/details/72636809 pcl::PointCloud<pcl::PointXYZRGBA ...
- 用conda创建一个tensorflow 虚拟环境
创建your——user——name = tensorflow 的虚拟环境 xinpingdeMacBook-Pro:~ xinpingbao$ conda create -n tensorflow ...
- Luogu 4069 [SDOI2016]游戏
BZOJ 4515 树链剖分 + 李超线段树 要求支持区间插入一条线段,然后查询一个区间内的最小值.可以使用李超线段树解决,因为要维护一个区间内的最小值,所以每一个结点再维护一个$res$表示这个区间 ...