首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# Excel 匯入資料重複檢查:DataTable 自我比對與資料庫交叉比對兩大策略

     編輯:關於C#

業務情境

從 Excel 匯入資料前,常需檢查兩類重複:

  1. 檔案內部重複: Excel 自身某幾欄組合鍵值重複。
  2. 跨資料庫重複: 匯入資料與現有資料庫資料鍵值衝突。

策略一:DataTable 內部自我比對

方法 A:使用 DataView.RowFilter(推薦,效能較好)

// 假設 dt 為已填充的 DataTable,需檢查 Col1+Col2+Col3 組合唯一
var view = dt.DefaultView;
view.RowFilter = "Col1 = '值1' AND Col2 = '值2' AND Col3 = '值3'";
// view.Count > 0 表示有重複

或動態建構:

string filter = $"Col1 = '{val1}' AND Col2 = '{val2}' AND Col3 = '{val3}'";
var dupRows = dt.Select(filter); // 回傳 DataRow[]

方法 B:雙層迴圈手動比對(適合邏輯複雜、欄位型別不一)

/// 
/// 掃描 DataTable 找出重複列索引(以第 1、4、8 欄組合鍵為例)
/// 
private string FindDuplicateRows(DataTable dt)
{
    var clone = dt.Clone(); // 僅複製結構,不複製資料
    foreach (DataRow row in dt.Rows) clone.ImportRow(row);

    var msg = new System.Text.StringBuilder();
    for (int i = clone.Rows.Count - 1; i >= 0; i--)
    {
        var key1 = clone.Rows[i][1]?.ToString().Trim();
        var key2 = clone.Rows[i][4]?.ToString().Trim();
        var key3 = clone.Rows[i][8]?.ToString().Trim();

        clone.Rows[i].Delete();
        clone.AcceptChanges();

        for (int j = clone.Rows.Count - 1; j >= 0; j--)
        {
            if (key1 == clone.Rows[j][1]?.ToString().Trim() &&
                key2 == clone.Rows[j][4]?.ToString().Trim() &&
                key3 == clone.Rows[j][8]?.ToString().Trim())
            {
                msg.AppendLine($"第 {i + 1} 列重複");
                break;
            }
        }
    }
    return msg.ToString();
}

注意: 必須用 dt.Clone() + ImportRow 建立獨立副本,不可直接 var clone = dt;(那只是參考指派)。

策略二:跨資料庫重複檢查

方案 A:逐筆查詢資料庫(資料量 < 100 筆適用)

foreach (DataRow row in dt.Rows)
{
    string sql = "SELECT COUNT(*) FROM TargetTable WHERE Key1=@k1 AND Key2=@k2 AND Key3=@k3";
    // 參數化查詢...
    if ((int)cmd.ExecuteScalar() > 0) 記錄重複;
}

缺點:2000 筆約需 7 分 40 秒(單筆 ~2.3 秒),網路延遲放大。

方案 B:一次撈取資料庫比對鍵值至 DataSet,記憶體中比對(大量資料首選)

// 1. 撈取資料庫所有比對鍵值
var dbKeys = new HashSet();
using (var da = new SqlDataAdapter("SELECT Key1, Key2, Key3 FROM TargetTable", conn))
{
    var ds = new DataSet();
    da.Fill(ds);
    foreach (DataRow r in ds.Tables[0].Rows)
        dbKeys.Add($"{r[0]}|{r[1]}|{r[2]}"); // 組合鍵字串
}

// 2. 逐筆比對
foreach (DataRow row in dt.Rows)
{
    string composite = $"{row[1]}|{row[4]}|{row[8]}";
    if (dbKeys.Contains(composite)) 記錄重複;
}

優點:單次資料庫往返,記憶體中 HashSet O(1) 查找,2000 筆可在秒級完成。

效能比較摘要

方案適用資料量2000 筆估計耗時複雜度
逐筆查 DB< 100~460 秒O(N) × DB Roundtrip
DataSet + HashSet任意< 5 秒O(N) + O(M)
DataTable.Select/RowFilter純內部比對極快O(N²) 最差,但 N 小時可接受

參考資源

原文連結:https://www.bianceng.cn/Programming/csharp/201410/45747.htm

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved