在C#应用程序中,利用表值参数过滤重复,批量向数据库导入数据,并且返回重复数据

  在很多情况下,应用程序都需要实现excel数据导入功能,数据如果只有几十条,或上百条,甚至上千条,速度还好。

  但是不仅如此,如果客户提供给你的excel本身存在着重复数据,或是excel中的某些数据已经在数据库存在,那这时,在向数据库插入数据前你还得判重,如果不存在才进行导入

通常,我们第一步就会通过上传的方式把excel中的数据读到内存,然后通过循环的方式得出一条一条数据,接着对于每条数据用关键字段去往数据库中进行一次查重,若存在则不做事情,若

不存在则向数据库中插入一条数据。这样一来,我们每一条数据都会与数据库打两次交道,众所周知,每连接一次数据库那是需要时间的,次数一多相当影响性能。若是成千上万条数据的话,可

想而知,这个导入过程会有多慢,尤其是Web应用程序,很有可能在我的请求还没执行完,突然程序就被终止了。

当然,还有个办法,就是拼SQL,每循环一条数据,首先判断,若不重复,我写一条SQL语句保存在某个变量中,直到循环到最后一条,可能会拼出多条Insert语句,最后送到数据库一次执

行,但是大家有没有想过,一旦数据量过大,几万,或几十万条数据拼成的字符串可想而知会有多长,送到数据库就会有被截断的可能。更何况还是逃离不了每次都要查询重复的惨况。

  一般来说,SQL语句离数据库端越近,执行效率越高,有没有可能,我把所要插入的数据集合一次性送给数据库,让判断重复,插入,返回重复数据的工作统统由数据库来执行呢?这样我只

要与数据库打一次交道,等待数据库给我结果就行。那么接下来就是我要讲到的利用表值参数来完成这一功能。

  由于为了讲述,例子中的表都比较简单

  1.首先我们来创建一张表(建库的过程在这里我就不说明了,为了大家看得清晰,尽量去除了无关的脚本行)

 1 CREATE TABLE [dbo].[BulkTestTable](
 2     [Id] [int] NOT NULL,
 3     [UserName] [nvarchar](32) NULL,
 4     [Pwd] [varchar](16) NULL,
 5 PRIMARY KEY CLUSTERED
 6 (
 7     [Id] ASC
 8 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
 9 ) ON [PRIMARY]
10
11 GO

2.创建表值类型

 1 USE [BulkTestDB]
 2 GO
 3
 4 /****** Object:  UserDefinedTableType [dbo].[BulkTestTableType]    Script Date: 07/08/2015 16:04:38 ******/
 5 CREATE TYPE [dbo].[BulkTestTableType] AS TABLE(
 6     [Id] [int] NULL,
 7     [UserName] [nvarchar](32) NULL,
 8     [Pwd] [varchar](16) NULL
 9 )
10 GO

3.写批量插入的存储过程

1 CREATE procedure [dbo].[usp_BulkTestTable_Import] 2 (@paratable as BulkTestTableType readonly) --此处的BulkTestTableType就是上面所定义的表类型,实际不用对它进行操作,只需要在程序中传入一个表给它,然后从它里面进行读取

3 AS 
4 Insert INTO dbo.BulkTestTable(Id,UserName,Pwd) 5 select * from @paratable A 6 WHERE Not EXISTS(select B.Id from BulkTestTable B WHERE B.Id=A.Id)

7 SELECT * from @paratable A WHERE EXISTS (select B.Id from BulkTestTable B WHERE B.Id=A.Id) --查询出重复的记录8 GO

在这里,我的Id不是自动增长的,仅仅是主键而已,所以这里通过Id来判断记录是否唯一或重复

接下来在C#代码里面写一个导入方法,调用这个存储过程。

这里的参数dt就是我们导入excel时生成的DataTable,这个DataTable的表结构也就是列要与我们定义的表值“BulkTestTableType”结构相同,返回值就是我们所要的重复记录
1  public static DataSet BatchInsert(DataTable dt)
2     {
3         SqlParameter parameter = new SqlParameter("@paratable",dt);
4         parameter.SqlDbType = SqlDbType.Structured;
5         parameter.TypeName = "BulkTestTableType"; //这里的类型名称应与我们定义的表值名称相同

6 SqlParameter[] sqlParameters = new SqlParameter[] { parameter }; 

7return SqlHelper.RunProcedure(CommandType.StoredProcedure, "usp_BulkTestTable_Import", sqlParameters); 
8 }

以上就是完整的代码,当然,怎么在内存中创建表,怎么写数据库访问方法我这里就不说明了,大家都知道。小白写文章,大家共同交流,勿喷

时间: 2024-07-29 15:42:20

在C#应用程序中,利用表值参数过滤重复,批量向数据库导入数据,并且返回重复数据的相关文章

学习Shell脚本编程(第3期)_在Shell程序中使用的参数

位置参数 内部参数 如同ls命令可以接受目录等作为它的参数一样,在Shell编程时同样可以使用参数.Shell程序中的参数分为位置参数和内部参数等. 3.1 位置参数 由系统提供的参数称为位置参数.位置参数的值可以用$N得到,N是一个数字,如果为1,即$1.类似C语言中的数组,Linux会把输入的命令字符串分段并给每段进行标号,标号从0开始.第0号为程序名字,从1开始就表示传递给程序的参数.如$0表示程序的名字,$1表示传递给程序的第一个参数,以此类推. 3.2 内部参数 上述过程中的$0是一个

Android中利用ant进行多渠道循环批量打包

公司负责Android开发的小伙伴学习能力稍微偏弱,交代给他的自动化打包的任务,弄了好久依然没有成效.无奈只好亲自出手. 没有想到过程很顺利,我完全按照如下文章的步骤进行: 主要参考: Android中利用ant进行多渠道循环批量打包(一) Android中利用ant进行多渠道循环批量打包(二) 次要参考:?? Mac中用Ant实现Android的批量打包碰到的一些问题以及解决方法 Android Ant 批量多渠道打包实例.md [Android分享]?最新的Android Sdk 使用Ant

微信小程序中利用时间选择器和js无计算实现定时器(将字符串或秒数转换成倒计时)

转载注明出处 今天写小程序,有一个需求就是用户选择时间,然后我这边就要开始倒计时. 因为小程序的限制,所以直接选用时间选择器作为选择定时器的小时和分钟.唯一的缺点就是不能选择秒. 一开始的想法是选择的到一个字符串以后,截取字符串转换成数字然后和以前一样不停的计算.什么计算秒数,换算成分数啊之类的 想想虽然不难但还是太麻烦了.就想有没有简单易懂的实现方法. 首先想到的就是js中的Date() 因为这个函数可以传字符串获取毫秒数,传毫秒数获取字符串.那么总体上来看,应该是可行的. 思路: 首先我们的

在java程序中利用线程

package 第十一章; import java.awt.Button; import java.awt.Color; import java.awt.Font; import java.awt.Frame; import java.awt.Label; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.*; publi

在程序中利用信号量同步来模拟生产者与消费者

信号量同步的概念: 一组并发进程进行相互合作.相互等待,使得各进程按一定的顺序执行的过程称为进程间的同步. customer.c product.c 运行生产者 运行消费者:

mapper文件中“添加一条新数据并返回此数据的ID(主键)”的方法

在mapper文件的insert语句前加上<selectKey>标签即可 如下: 添加前测试: 添加后测试: 原文地址:https://www.cnblogs.com/rgever/p/9473580.html

【译】 AWK教程指南 6在AWK程序中使用Shell命令

awk程序中允许调用Shell指令,并提供管道解决awk与系统间数据传递的问题.所以awk很容易使用系统资源,读者可利用这个特点来编写某些适用的系统工具. 范例:写一个awk程序来打印出线上人数. 将下列程序建文件,命名为 count.awk BEGIN { while ( "who" | getline ) n++ print n } 并执行下列命令: $ awk -f count.awk 执行结果将会打印出目前在线人数. 说 明: 1. awk 程序并不一定要处理数据文件,以本例而

【数据库MSSQL2008】使用表值参数快速插入数据

项目中需要将解析原始文件获得的10W左右的数据插入数据库,如果使用原始的sql语句"insert into",无论是循环插入还是批量插入,不是效率慢就是系统内存消耗殆尽,无法满足需求. 经网上查阅,发现mssql从2008起开始,数据库支持以表值参数的方式批量插入数据,使用该方式,一次性插入10W条数据也不过是3-5秒钟的事情,一切开始变得美好起来~ 使用表值参数批量插入数据的步骤和要点: 1.数据源需要是DataTable形式,且字段顺序必须和相应的数据库的数据表的字段属性.顺序一致

SQL Server 2008 表变量参数(表值参数)用法

表值参数是 SQL Server 2008 中的新参数类型.表值参数是使用用户定义的表类型来声明的.使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程或函数)发送多行数据. 表值参数与 OLE DB 和 ODBC 中的参数数组类似,但具有更高的灵活性,且与 Transact-SQL 的集成更紧密.表值参数的另一个优势是能够参与基于数据集的操作. (注意:Transact-SQL 通过引用向例程传递表值参数,以避免创建输入数据的副本.) 在 Tra