You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SqlBulkCopy.WriteToServer()时如何忽略重复与NULL值?

问题场景与现有代码

1. 数据库连接方法

private void connection()    
    sqlconn = ConfigurationManager.ConnectionStrings["SqlCom"].ConnectionString;    
    con = new SqlConnection(sqlconn);    

2. CSV数据批量插入方法

private void InsertCSVRecords(DataTable csvdt)  
{
    connection();  

    // 创建SqlBulkCopy对象    
    SqlBulkCopy objbulk = new SqlBulkCopy(con);  

    // 指定目标表名    
    objbulk.DestinationTableName = "Users";  

    // 映射表列
    objbulk.ColumnMappings.Add("Name", "Name");  
    objbulk.ColumnMappings.Add("Email", "Email");  
   
    // 插入数据到数据库    
    con.Open();  
    objbulk.WriteToServer(csvdt);  
    con.Close();  
} 

3. 从CSV文件读取数据到DataTable

protected void Button1_Click(object sender, EventArgs e)  
{  
    DataTable tblcsv = new DataTable();  
    // 创建列  
    tblcsv.Columns.Add("Name");  
    tblcsv.Columns.Add("Email");  
   
    string CSVFilePath = Path.GetFullPath(FileUpload1.PostedFile.FileName);  
      
    string ReadCSV = File.ReadAllText(CSVFilePath);  
    
    foreach (string csvRow in ReadCSV.Split('\n'))  
    {  
        if (!string.IsNullOrEmpty(csvRow))  
        {  
            // 将每行添加到DataTable  
            tblcsv.Rows.Add();  
            int count = 0;  

            foreach (string FileRec in csvRow.Split(','))  
            {  
                tblcsv.Rows[tblcsv.Rows.Count - 1][count] = FileRec;  
                count++;  
            }  
        }    
    }  

    // 调用插入方法  
    InsertCSVRecords(tblcsv);  
} 

4. 创建带主键的表的尝试

protected void CreateT_Click(object sender, EventArgs e)
{
    string Users = "";
    string Email = "";
    string Name = "";

    connection();

    SqlCommand command = new SqlCommand();
    command.Connection = con;
  
    command.CommandText = "CREATE TABLE " + Users + "(" + Email + " varchar(255), " + Name + " varchar(255), PRIMARY KEY (Email));";
            
    con.Open();
    command.ExecuteNonQuery();
    con.Close();        
}

核心问题

使用objbulk.WriteToServer(csvdt);批量插入时,无法忽略重复值;设置Email为主键后,插入重复值会直接抛出异常。需求是:将CSV中的数据插入表时,自动忽略重复的Email值以及NULL值。


解决方案

方案一:提前在DataTable中过滤无效数据

在调用批量插入方法前,对读取到的DataTable进行清洗,去掉Email为空/NULL的记录,同时去重:

// 过滤Email为空或NULL的记录,同时按Email去重
DataTable cleanedDt = tblcsv.AsEnumerable()
    .Where(row => !string.IsNullOrEmpty(row.Field<string>("Email")?.Trim()))
    .GroupBy(row => row.Field<string>("Email").Trim())
    .Select(g => g.First())
    .CopyToDataTable();

// 调用插入方法,传入清洗后的DataTable
InsertCSVRecords(cleanedDt);

方案二:使用临时表+MERGE语句(适合大数据量场景)

如果CSV数据量较大,内存过滤效率低,可以先批量插入临时表,再通过SQL的MERGE语句同步有效数据到正式表,自动忽略重复值:

private void InsertCSVRecords(DataTable csvdt)  
{
    connection();  

    // 创建临时表(如果不存在)
    using (SqlCommand cmd = new SqlCommand(@"
        IF OBJECT_ID('tempdb..#TempUsers') IS NOT NULL
            DROP TABLE #TempUsers;
        CREATE TABLE #TempUsers (
            Name varchar(255),
            Email varchar(255)
        );", con))
    {
        con.Open();
        cmd.ExecuteNonQuery();
    }

    // 批量插入到临时表
    using (SqlBulkCopy objbulk = new SqlBulkCopy(con))
    {
        objbulk.DestinationTableName = "#TempUsers";
        objbulk.ColumnMappings.Add("Name", "Name");  
        objbulk.ColumnMappings.Add("Email", "Email");  
        objbulk.WriteToServer(csvdt);
    }

    // 用MERGE同步数据,忽略重复和无效Email
    using (SqlCommand cmd = new SqlCommand(@"
        MERGE INTO Users AS Target
        USING (
            SELECT Name, Email 
            FROM #TempUsers 
            WHERE Email IS NOT NULL AND LTRIM(RTRIM(Email)) != ''
        ) AS Source
        ON Target.Email = Source.Email
        WHEN NOT MATCHED THEN
            INSERT (Name, Email) VALUES (Source.Name, Source.Email);", con))
    {
        cmd.ExecuteNonQuery();
    }

    con.Close();  
} 

补充:修正建表方法的错误

当前建表代码中变量为空字符串,会导致SQL语句无效,修正后:

protected void CreateT_Click(object sender, EventArgs e)
{
    connection();

    using (SqlCommand command = new SqlCommand(@"
        CREATE TABLE Users(
            Name varchar(255), 
            Email varchar(255) NOT NULL, 
            PRIMARY KEY (Email)
        );", con))
    {
        con.Open();
        command.ExecuteNonQuery();
        con.Close();        
    }
}

内容的提问来源于stack exchange,提问作者Valeso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 06:15:03