CSV导入SQL Server避免重复数据插入的技术问询
解决CSV导入SQL Server时重复插入旧数据的问题
我来帮你搞定这个重复插入的麻烦!你现在的逐行插入方式不仅效率低,还没法过滤重复数据,用「临时表+批量导入+去重插入」的方案正好解决这个问题,具体步骤和代码如下:
核心思路
- 先用SqlBulkCopy把CSV数据批量导入到SQL Server的临时表(比逐行插入效率高太多,尤其面对15000+条数据时)
- 再通过SQL语句从临时表往正式表
Silver_Robot插入数据,同时用WHERE NOT EXISTS过滤掉已经存在的记录(需要先确定业务上的唯一标识字段)
具体实现步骤
1. 确定唯一标识字段
首先得明确哪些字段组合能唯一标识一条记录,比如Program_S+Start_Date_S+Start_Time_S?这一步是去重的关键,务必根据你的业务逻辑确认。下面的代码会基于这个组合示例。
2. 修改C#代码
替换原来的逐行插入逻辑,改成批量导入临时表+去重插入:
private void Save_Import_Data_SQL(DataTable importData) { using (SqlConnection conn = new SqlConnection(myconnstring)) { conn.Open(); // 1. 创建会话级临时表(会话结束自动销毁) using (SqlCommand createTempTableCmd = new SqlCommand(@" CREATE TABLE #TempSilverRobot ( Program NVARCHAR(255), [Group] NVARCHAR(255), Start_Date DATETIME, Start_Time DECIMAL(18,2), Pieces DECIMAL(18,2), Finish_Date DATETIME, Finish_Time DECIMAL(18,2), Average_Part_Cycle_Time DECIMAL(18,2), Mode NVARCHAR(50), Length DECIMAL(18,2) )", conn)) { createTempTableCmd.ExecuteNonQuery(); } // 2. 用SqlBulkCopy批量导入DataTable到临时表 using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn)) { // 映射DataTable列与临时表列(列名一致可省略,但手动映射更稳妥) bulkCopy.ColumnMappings.Add("Program", "Program"); bulkCopy.ColumnMappings.Add("Group", "Group"); bulkCopy.ColumnMappings.Add("Start date", "Start_Date"); bulkCopy.ColumnMappings.Add("Start time", "Start_Time"); bulkCopy.ColumnMappings.Add("Pieces", "Pieces"); bulkCopy.ColumnMappings.Add("Finish date", "Finish_Date"); bulkCopy.ColumnMappings.Add("Finish time", "Finish_Time"); bulkCopy.ColumnMappings.Add("Average part cycle time", "Average_Part_Cycle_Time"); bulkCopy.ColumnMappings.Add("Mode", "Mode"); bulkCopy.ColumnMappings.Add("Length_pa", "Length"); bulkCopy.DestinationTableName = "#TempSilverRobot"; bulkCopy.WriteToServer(importData); } // 3. 从临时表插入正式表,过滤重复项 // 注意:把WHERE NOT EXISTS里的条件替换成你实际的唯一标识字段组合 using (SqlCommand insertCmd = new SqlCommand(@" INSERT INTO Silver_Robot( Program_S, Grpup_S, Start_Date_S, Start_Time_S, Pieces_S, Finish_Date_S, Finish_Time_S, Average_Part_Cycle_Time_S, Mode_S, Length_S ) SELECT Program, [Group], Start_Date, Start_Time, Pieces, Finish_Date, Finish_Time, Average_Part_Cycle_Time, Mode, Length FROM #TempSilverRobot temp WHERE NOT EXISTS ( SELECT 1 FROM Silver_Robot sr WHERE sr.Program_S = temp.Program AND sr.Start_Date_S = temp.Start_Date AND sr.Start_Time_S = temp.Start_Time )", conn)) { int rowsInserted = insertCmd.ExecuteNonQuery(); // 可选:打印插入行数用于调试 Console.WriteLine($"成功插入{rowsInserted}条新数据"); } // 临时表会在连接关闭后自动销毁,无需手动删除 } }
3. 优化点说明
- 批量导入:
SqlBulkCopy比逐行ExecuteNonQuery效率提升数倍,上万条数据的导入速度会明显变快。 - 去重逻辑:
WHERE NOT EXISTS会精准检查正式表中是否已有相同记录,仅插入全新数据。如果需要更新已有记录(比如数据有修改),可以用MERGE语句替代INSERT...SELECT。 - 临时表:会话级临时表(
#开头)仅在当前数据库连接中存在,连接关闭后自动清理,不会残留冗余数据。
注意事项
- 务必确保唯一标识字段组合的准确性,否则会出现重复插入或漏插的问题。
- 如果
Silver_Robot表有主键或唯一约束,也可以借助约束特性配合IGNORE_DUP_KEY,但WHERE NOT EXISTS的方式更直观可控。
内容的提问来源于stack exchange,提问作者Dinu Kuruppu
相关产品推荐
相关产品推荐

