SQL Server大量数据秒级插入/新增/删除

转载自诗人江湖老,原文地址

        /// <summary>/// 快速保存数据,自动识别insert和update/// </summary>/// <param name="_sourceTable">需要保存的源数据表</param>/// <param name="_sqlCon">数据库连接</param>/// <param name="_errorMsg">输出参数,错误信息</param>/// <param name="KeepConnectionAlive">是否保持连接,可选参数,默认否</param>/// <returns></returns>private bool BulkSave(DataTable _sourceTable, SqlConnection _sqlCon,out string _errorMsg, bool _keepConnectionAlive = false){bool result = true;_errorMsg = string.Empty;DataTable sourceTable = _sourceTable.Copy();if (string.IsNullOrEmpty(sourceTable.TableName)){_errorMsg = "数据源表的TableName属性不能为空!";return false;}List<string> colList = new List<string>();foreach (DataColumn col in sourceTable.Columns){colList.Add(col.ColumnName);}int updateNum, insertNum;updateNum = insertNum = 0;try{#regionif (_sqlCon.State == ConnectionState.Closed){_sqlCon.Open();}SqlCommand cmd = _sqlCon.CreateCommand();StringBuilder sb = new StringBuilder();DataTable pk = new DataTable();string tempTableName = "#" + sourceTable.TableName;//#表名 为当前连接有效的临时表 ##表名 为全局有效的临时表string tempTableFullCloumn = "";//临时表获取表结构命令字符串string updateSetStr = "";//update set 命令字符串string insertWhereStr = "";//insert 命令用来排除已经存在记录的 not exist 命令中where条件字符串string insertColumnStr = "";//列名字符串string tempColmunstr = "";//t.+列名 字符串sb = new StringBuilder();sb.AppendFormat(@"select a.name as Name,b.name as 'type',a.length as 'length' ,a.collation as 'collation' from syscolumns aleft join systypes b on a.xtype = b.xtype where colid in (select colid from sysindexkeys where id = object_id('{0}') and indid = (select indid from sysindexes where name = (select name from sysobjects where xtype='PK' and parent_obj = object_id('{0}')))) and a.id = object_id('{0}');", sourceTable.TableName);cmd.CommandText = sb.ToString();pk.Load(cmd.ExecuteReader());//查询主键列表#endregion#region/* 利用传递进来的DataTable列名列表,从数据库的源表获取* 临时表的表结构*/for (int i = 0; i < colList.Count; i++){/* 如果当前列是主键,set命令字符串跳过不作处理,* 临时表获取表结构命令字符串不论何种情况都不跳过 */if (pk.Select("Name= '" + (colList[i]) + "'").Length > 0){string sql = string.Format("SELECT COLUMNPROPERTY(OBJECT_ID('{0}'), '{1}', 'IsIdentity')", sourceTable.TableName, colList[i]);cmd.CommandText = sql;bool  flag = Convert.ToBoolean(cmd.ExecuteScalar());if (!flag){if (updateSetStr.Length > 0){updateSetStr += ",";}if (insertColumnStr.Length > 0){insertColumnStr += ",";}if (tempColmunstr.Length > 0){tempColmunstr += ",";}updateSetStr += colList[i] + "= t." + colList[i];insertColumnStr += colList[i];tempColmunstr += colList[i];}}else{if (updateSetStr.Length > 0){updateSetStr += ",";}if (insertColumnStr.Length > 0){insertColumnStr += ",";}if (tempColmunstr.Length > 0){tempColmunstr += ",";}updateSetStr += colList[i] + "= t." + colList[i];insertColumnStr += colList[i];tempColmunstr += colList[i];}if (i > 0){tempTableFullCloumn += ",";}tempTableFullCloumn += "s." + colList[i];}#endregion#regionsb = new StringBuilder();sb.AppendFormat("select top 0 {0} into {1} from {2} s;", tempTableFullCloumn, tempTableName, sourceTable.TableName);cmd.CommandText = sb.ToString();cmd.ExecuteNonQuery();//创建临时表/* 根据获得的目标表主键,来为SQL Server 系统中的临时表增加相应的非主键但是数据相等* 的 影射列,因为有些系统的主键为自增类型,在调用bulk.WriteToServer方法的时候,自增主键会* 在临时表中从0开始计算,没办法用临时表的主键和目标表的主键做 where 条件,故用影射列代替*/for (int i = 0; i < pk.Rows.Count; i++){if (i > 0){insertWhereStr += " and ";}string newColName = pk.Rows[i]["name"].ToString() + "New";sb = new StringBuilder();switch (pk.Rows[i]["type"].ToString()){case "char":case "varchar":case "nchar":case "nvarchar":sb.AppendFormat("alter table {0} add {1} {2}({3}) ", tempTableName, newColName, pk.Rows[i]["Type"].ToString(), pk.Rows[i]["length"]);break;default:sb.AppendFormat("alter table {0} add {1} {2} ", tempTableName, newColName, pk.Rows[i]["Type"].ToString());break;}if (!(pk.Rows[i]["collation"] is DBNull)){sb.AppendFormat("COLLATE {0}", pk.Rows[i]["collation"]);}cmd.CommandText = sb.ToString();cmd.ExecuteNonQuery();sourceTable.Columns.Add(new DataColumn(newColName, sourceTable.Columns[pk.Rows[i]["name"].ToString()].DataType));foreach (DataRow dr in sourceTable.Rows){dr[newColName] = dr[pk.Rows[i]["name"].ToString()].ToString().Trim();}insertWhereStr += "t." + newColName + "=s." + pk.Rows[i]["name"];}using (System.Data.SqlClient.SqlBulkCopy bulk = new System.Data.SqlClient.SqlBulkCopy(_sqlCon)){//string SQl = "select * from #bulktable ";//DataTable tempx = new DataTable();//cmd.CommandText = SQl;//tempx.Load(cmd.ExecuteReader());//_souceTable.Rows[0]["unit_name"] = string.Empty;//_souceTable.Rows[1]["unit_name"] = string.Empty;int colCount = sourceTable.Columns.Count;foreach (DataRow row in sourceTable.Rows){for (int i = 0; i < colCount; i++){row[i] = row[i].ToString().Trim();}}bulk.DestinationTableName = tempTableName;bulk.BulkCopyTimeout = 36000;try{bulk.WriteToServer(sourceTable);//将数据写入临时表//string sql = "select * from #bulktable";//SqlDataAdapter sda = new SqlDataAdapter(sql, _sqlCon);//DataTable dt = new DataTable();//sda.Fill(dt);}catch (Exception e){_errorMsg = e.Message;result = false;//MessageBox.Show(e.Message);//return e.Message.Trim();}}#endregion#regionif (insertWhereStr.Equals(""))//如果不存在主键{sb = new StringBuilder();sb.AppendFormat("insert into {0} select {1} from {2} s;", sourceTable.TableName, tempTableFullCloumn, tempTableName);cmd.CommandText = sb.ToString();insertNum = cmd.ExecuteNonQuery();//插入临时表数据到目的表//_errorMsg = "1";}else{sb = new StringBuilder();sb.AppendFormat("update {0} set {1} from( {2} t INNER JOIN {0} s on {3} );",sourceTable.TableName, updateSetStr, tempTableName, insertWhereStr);//cmd.CommandText = sb.ToString();//Stopwatch sw = new Stopwatch();//sw.Start();//updateNum = cmd.ExecuteNonQuery();//更新已存在主键数据//_errorMsg += "更新" + updateNum + "条记录";//sw.Stop();//sb = new StringBuilder();sb.AppendFormat("insert into {0}({4}) select {1} from {2} t where not EXISTS(select 1 from {0} s where {3});",sourceTable.TableName, tempColmunstr, tempTableName, insertWhereStr, insertColumnStr);cmd.CommandText = sb.ToString();//insertNum = cmd.ExecuteNonQuery();//插入新数据//_errorMsg += "插入" + insertNum + "条记录";//MessageBox.Show("共用时" + sw.Elapsed + "\n 共新增:" + insertNum + "条记录,更新:" + updateNum + "条记录!");//return_str = "1";var st = _sqlCon.BeginTransaction();cmd.Transaction = st;try{cmd.ExecuteNonQuery();st.Commit();}catch (Exception ee){_errorMsg += ee.Message;result = false;st.Rollback();}}#endregion}catch (Exception e){_errorMsg = e.Message.Trim();result = false;}finally{if (!_keepConnectionAlive && _sqlCon.State == ConnectionState.Open){_sqlCon.Close();}}return result;}

2.快速删除,该方法有四个参数,第一个参数为数据库连接,第二个参数为需要删除的DataTable,该参数的TableName属性需要设置为数据库中目标数据表的表名,第三个参数为输出参数,如果删除过程中发生错误则错误信息会输出在这个参数里面,第四个参数为可选参数,是否保持连接为打开状态。

        /// <summary>/// 快速删除/// </summary>/// <param name="_sourceTable">需要删除的源数据表</param>/// <param name="_sqlCon">数据库连接</param>/// <param name="_errorMsg">输出参数,错误信息</param>/// <param name="_keepConnectionAlive">是否保持连接,可选参数,默认否</param>/// <returns></returns>private bool BulkDelete(DataTable _sourceTable, SqlConnection _sqlCon, out string _errorMsg, bool _keepConnectionAlive = false){bool result = true;_errorMsg = string.Empty;DataTable sourceTable = _sourceTable.Copy();string SQl = "";DataTable pkTable = new DataTable();DataSet ds = new DataSet();string whereStr = string.Empty;string colList = string.Empty;if (string.IsNullOrEmpty(sourceTable.TableName)){_errorMsg += "数据源表的TableName属性不能为空!";return false;}try{#region 检查数据表是否存在SqlCommand sqlComm = _sqlCon.CreateCommand();SqlDataAdapter sda = new SqlDataAdapter();string tempTableName = "#" + sourceTable.TableName;SQl = string.Format("select COUNT(*) from sysobjects where id = object_id(N'[{0}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1", sourceTable.TableName);sqlComm.CommandText = SQl;if (_sqlCon.State != ConnectionState.Open){_sqlCon.Open();}int count = Convert.ToInt32(sqlComm.ExecuteScalar());#endregionif (count == 0){_errorMsg += string.Format("在数据库中,找不到名为{0}的数据表!", sourceTable.TableName);}else{#region 获取主键信息SQl = string.Format(@"select a.name as Name,b.name as 'type',a.length as 'length' ,a.collation as 'collation' from syscolumns a left join systypes b on a.xtype = b.xtype where colid in (select colid from sysindexkeys where id = object_id('{0}') and indid = (select indid from sysindexes where name = (select name from sysobjects where xtype='PK' and parent_obj = object_id('{0}')))) and a.id = object_id('{0}');", sourceTable.TableName);sqlComm.CommandText = SQl;sda.SelectCommand = sqlComm;sda.Fill(ds, "pkTable");pkTable = ds.Tables["pkTable"];#endregion#region 生成where条件foreach (DataColumn col in sourceTable.Columns){colList += colList.Length == 0 ? col.ColumnName : "," + col.ColumnName;}SQl = string.Format("select top 0 {0} into {1} from {2}", colList, tempTableName, sourceTable.TableName);sqlComm.CommandText = SQl;sqlComm.ExecuteNonQuery();if (pkTable.Rows.Count <= 0){_errorMsg += string.Format("获取{0}表主键信息失败,请重试或者检查数据库!", sourceTable.TableName);}else{foreach (DataRow dr in pkTable.Rows){string newColName = dr["name"].ToString() + "New";/* 如果当前列是主键,set命令字符串跳过不作处理,* 临时表获取表结构命令字符串不论何种情况都不跳过 */SQl = string.Format("SELECT COLUMNPROPERTY(OBJECT_ID('{0}'), '{1}', 'IsIdentity')", sourceTable.TableName, dr["name"]);sqlComm.CommandText = SQl;bool  flag = Convert.ToBoolean(sqlComm.ExecuteScalar());switch (dr["type"].ToString()){case "char":case "varchar":case "nchar":case "nvarchar":SQl = string.Format("alter table {0} add {1} {2}({3}) ", tempTableName, newColName, dr["Type"].ToString(), dr["length"]);break;default:SQl = string.Format("alter table {0} add {1} {2} ", tempTableName, newColName, dr["Type"].ToString());break;}if (!(dr["collation"] is DBNull)){SQl = string.Format("{0} COLLATE {1}", SQl, dr["collation"]);}sqlComm.CommandText = SQl;sqlComm.ExecuteNonQuery();whereStr += string.IsNullOrEmpty(whereStr) ? string.Format("{0}.{2} in( select {1}.[{3}] from {1} )", sourceTable.TableName, tempTableName, dr["name"], newColName) : string.Format(" and {0}.{2} in( select {1}.[{3}] from {1} )", sourceTable.TableName, tempTableName, dr["name"], newColName);sourceTable.Columns.Add(new DataColumn(newColName, sourceTable.Columns[dr["name"].ToString()].DataType));foreach (DataRow row in sourceTable.Rows){row[newColName] = row[dr["name"].ToString()].ToString().Trim();}}}}#endregion#region 将数据放进临时表SqlBulkCopy bulk = new SqlBulkCopy(_sqlCon);bulk.DestinationTableName = tempTableName;bulk.BulkCopyTimeout = 3600;try{bulk.WriteToServer(sourceTable);}catch (Exception ee){_errorMsg += ee.Message;bulk.Close();}#endregion#region 开始删除//SQl = string.Format("select * from {0}", tempTableName);//sqlComm.CommandText = SQl;//sda.SelectCommand = sqlComm;//sda.Fill(ds, tempTableName);SQl = string.Format(@" DELETE FROM {0}  WHERE {1}", sourceTable.TableName, whereStr);sqlComm.CommandText = SQl;var tx = _sqlCon.BeginTransaction();try{sqlComm.Transaction = tx;count = sqlComm.ExecuteNonQuery();tx.Commit();_errorMsg += string.Format("应该删除{0}条记录\r\n共删除{1}条记录!", sourceTable.Rows.Count, count);}catch (Exception ee){_errorMsg += ee.Message;tx.Rollback();}#endregion}catch (Exception e){_errorMsg += e.Message;}finally{if (_sqlCon.State == ConnectionState.Open && !_keepConnectionAlive){_sqlCon.Close();}}return result;}

添加链接描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548645.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在当前主机添加两块网卡,将两块网卡绑定实现网卡冗余操作。

编辑虚拟网络接口配置文件,指定网卡IP 1. change the /etc/sysconfig/network-scripts/ifcfg-bond0 configuration. # cat ifcfg-bond0 DEVICEbond0 BOOTPROTOstatic IPADDR172.24.80.168 NETMASK255.255.255.0 BROADCAST172.24.80.250 ONBOOTyes TYPEEthernet # 不…

如何发布.Net MVC 网站项目(攻略集锦)

转载自诗人江湖老&#xff0c;原文地址 参考文献既然是攻略&#xff0c;就必然有参考文献&#xff0c;放在文章开头&#xff0c;以示敬意&#xff01; 1.MVC项目发布步骤 2.未能从程序集加载“System.ServiceModel.Activation.HttpModule” 3. Win7 IIS 另一个程序正在使用此…

ssh建立原理 及配置两台主机的远程连接实现免密登陆

一、SSH是什么&#xff1f;具体的实现有哪些&#xff1f; SSH是一种协议标准 SSH是用在安全远程登录以及其它安全网络服务 二、SSH原理&#xff1a; SSH为Secure Shell的缩写&#xff0c;默认端口22&#xff0c;由IETF的网络小组&#xff08;Network Working Group&…

ssh-scan处理手记

登陆一台Linux RedHat As4的服务器&#xff0c;发现有很多网络连接&#xff0c;为本机去连接其他服务器的22端口。再一看进程&#xff0c;好多ssh-scan的进程。估计是密码设得太简单&#xff0c;被人家黑了。处理思路&#xff1a;找到ssh-scan进程的相应程序文件&#xff0c;删…

常用 SQL Server 规范集锦

原文地址 常见的字段类型选择   &#xff11;.字符类型建议采用varchar/nvarchar数据类型   &#xff12;.金额货币建议采用money数据类型   &#xff13;.科学计数建议采用numeric数据类型   &#xff14;.自增长标识建议采用bigint数据类型 (数据量一大&#xff…

Linux服务器搭建----Web服务器(apache)

WWW的介绍 万维网&#xff08;亦作“Web”、“WWW”、“W3”&#xff0c;英文全称为“World Wide Web”&#xff09;&#xff0c;是一个由许多互相链接的超文本组成的系统&#xff0c;通过互联网访问。在这个系统中&#xff0c;每个有用的事物&#xff0c;称为一样“资源”&…

Pa interface issue——PA_EXCEED_ROUND_LIMIT

最近处理一个PA_TRANSACTION_INTERFACE_ALL的Error Error_code:PA_EXCEED_ROUND_LIMIT 原因是PA_EXCEED_ROUND_LIMIT is null or too small for cost*invoice_rate - cost*actual_rate. 就是说limit的value为空或者不满足金额*当前汇率与金额*录入时汇率的差额。 问题的难点在于…

C#实现 Linq 序列的Distinct—— IEnumerable.Distinct()——IEqualityComparer

转载自诗人江湖老&#xff0c;原文地址 在C#中使用List或者Collection的时候&#xff0c;我们经常需要使用到Distinct操作&#xff0c;但是微软默认提供的Distinct重载方法并不能满足我们的需求。这时候&#xff0c;我们就需要自己动手做一番工作了。 Distinct方法的重载 Linq…

F5 配置手册 -F5 BIG-IP 10.1-1-激活

F5 配置手册 F5 BIG-IP 10.1-1-激活 统一沟通(中国)有限公司 2012-01-29 前言&#xff1a; F5---太贵! 不过你如果有命运看到这个文章,F5也就不值钱了。 因为:F5提供测试版的虚拟机,我们买不起,总应该玩得起吧! 但愿F5提供更多的机会,给别人机会,也是给自己机会。 参照: 你也可…

[深入学习C#]利用反射给对象赋值

转载自诗人江湖老&#xff0c;原文地址  C#中利用反射能够获取对象的属性信息&#xff0c;也可以利用反射给对象赋值。 我们如果想利用凡是给一个对象属性赋值可以通过PropertyInfo.SetValue()方式进行赋值&#xff0c;但要注意值的类型要与属性保持一致。   假设我们有如下…

快速配置 Samba 将 Linux 目录映射为 Windows 驱动器

一、局域网内的 Linux 服务器上操作步骤&#xff1a;  1、安装samba&#xff08;CentOS Linux&#xff09;&#xff1a; yum install samba system-config-samba samba-client samba-common2、创建www账号 /usr/sbin/groupadd www/usr/sbin/useradd -g www wwwcat /etc/passw…

用委托来实现IEqualityComparer接口

转载自诗人江湖老&#xff0c;原文地址 class FuncEqualityComparer<T> : IEqualityComparer<T> {readonly Func<T, T, bool> _comparer;readonly Func<T, int> _hash;public FuncEqualityComparer( Func<T, T, bool> comparer ): this( compar…

Beginning iCloud in iOS 5 Tutorial Part 2(转载)

原文地址&#xff1a;http://www.raywenderlich.com/6031/beginning-icloud-in-ios-5-tutorial-part-2 Setting Up the User Interface The Xcode project template we chose already set up an empty view controller for us. We will extend it by adding the current docume…

JQuery Datatables 服务端分页简单应用学习

背景介绍 最近在一个简单小项目中碰到需要一个前端数据表格控件&#xff0c;在看了网上的资料后最终选择了JQuery Datatables。Datatables功能及其强大&#xff0c;基本满足我的所有需求&#xff0c;在加上其插件Editor具有inline模式&#xff0c;很多需要直接修改数据的功能不…

开源文化与开源社区

开源文化的形成  1998年2月8日&#xff0c;Bruce Perens发表的著名文章“TheOpen Source Definition”让当时众多的开源爱好者&#xff08;大多是***和程序员&#xff09;对开源理念有了一个清晰的认识。在那之后&#xff0c;更多的人开始关注开源所带来的实用意义和背后的文…

C#利用反射实现实体类ListT索引器

相关背景: 在项目开发中&#xff0c;我们经常会自定义一些实体类&#xff0c;在某些需要动态赋值的功能中&#xff0c;我们无法知道到下一个需要赋值的字段名称是什么&#xff0c;只知道会从其他返回需要赋值的字段名称和值&#xff0c;这时候就需要实现索引器了&#xff0c;就…

C#利用反射将Datatable转化为指定实体类ListT

背景介绍 在软件开发中肯定免不了和数据库打交道&#xff0c;我们对数据的增删改查最终会转化为SQL在数据库中执行。从SQLServer中查出数据一般有两种方式&#xff1a;一是ADO.NET直接写SQL语句从数据中查出数据&#xff0c;另一种是利用ORM框架得到数据。ADO.NET作为传统的数据…

Java API 设计清单

为什么80%的码农都做不了架构师&#xff1f;>>> 在设计Java API的时候总是有很多不同的规范和考量。与任何复杂的事物一样&#xff0c;这项工作往往就是在考验我们思考的缜密程度。就像飞行员起飞前的检查清单&#xff0c;这张清单将帮助软件设计者在设计Java API的…

利用FSMT进行文件服务器迁移及整合

当企业文件服务器&#xff08;DFS、共享文件夹等&#xff09;面临硬件更新、系统升级或文件服务器合并的情况时&#xff0c;往往会出现不确定的文件丢失、需要重新设置所有权限、无法将多个文件服务器集成到一台服务器上等问题&#xff0c;为了保证文件服务器的数据完整以及权限…

C#利用反射将实体类ListT转化为Datatable

背景介绍 C#中实体类的操作十分简便&#xff0c;一般情况下不需要涉及ADO.NET&#xff0c;如果需要将实体类转化为Datatable&#xff0c;这个时候就需要手动写一个方法了&#xff0c;代码如下图所示&#xff1a; public static class IEnumerableExtention{/// <summary>…