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

从CSV导入多行至SQL Server时生成唯一Num Contrat的问题

解决SQL Server主键重复问题的排查步骤

可能的原因及修复方案

1. 计数器未按原Num Contrat分组

如果脚本使用全局计数器(整个CSV只维护一个递增变量),而非为每个重复的原Num Contrat单独维护计数器,会导致不同原编号生成的新编号重复。比如原编号CONTRAT-001和CONTRAT-101的后两位都是01,全局计数器会让两者的后缀序列重叠,最终生成重复的新编号。

修复:
用哈希表按原Num Contrat分组管理计数器:

# 初始化哈希表存储每个原编号的当前计数器
$counterTable = @{}

foreach ($row in $csvData) {
    $originalNum = $row.'Num Contrat'
    # 首次处理该原编号时,初始化计数器为1
    if (-not $counterTable.ContainsKey($originalNum)) {
        $counterTable[$originalNum] = 1
    }
    # 生成两位格式的后缀(自动补零)
    $suffix = $counterTable[$originalNum].ToString("D2")
    # 生成新编号:原编号拼接后缀(可按需添加分隔符)
    $newNumContrat = "{0}-{1}" -f $originalNum, $suffix
    # 递增当前原编号的计数器
    $counterTable[$originalNum]++
    
    # 后续导入SQL的逻辑...
}

这样每个原编号的后缀独立递增,不会和其他原编号的序列冲突。

2. 新编号仅依赖原编号后两位

如果新编号是原编号后两位 + 后缀,而非完整原编号 + 后缀,只要两个不同原编号的后两位相同,就会生成重复的新编号(比如0101可能来自多个原编号)。

修复:
基于完整原编号生成新编号,示例:

# 直接拼接原编号与后缀
$newNumContrat = "{0}{1}" -f $originalNum, $suffix
# 或用分隔符区分原编号与后缀,避免格式混淆
$newNumContrat = "{0}-{1}" -f $originalNum, $suffix

3. 未处理数据库中已存在的编号

即使脚本生成的新编号在CSV内唯一,也可能和SQL Server中已有的主键重复。

修复:
导入前先查询数据库中已有的编号,生成新编号时检查是否重复:

# 从SQL查询现有编号并存入哈希集合(查询逻辑需自行实现)
$existingNums = Invoke-SqlCmd -ServerInstance "YourServer" -Database "YourDB" -Query "SELECT [Num Contrat] FROM Contrats" | Select-Object -ExpandProperty "Num Contrat"
$existingSet = [System.Collections.Generic.HashSet[string]]::new($existingNums)

foreach ($row in $csvData) {
    $originalNum = $row.'Num Contrat'
    if (-not $counterTable.ContainsKey($originalNum)) {
        $counterTable[$originalNum] = 1
    }
    # 循环生成直到找到未存在的编号
    do {
        $suffix = $counterTable[$originalNum].ToString("D2")
        $newNumContrat = "{0}-{1}" -f $originalNum, $suffix
        $counterTable[$originalNum]++
    } while ($existingSet.Contains($newNumContrat))
    
    # 将新编号加入集合,避免当前批次内重复
    $existingSet.Add($newNumContrat) | Out-Null
    # 导入SQL...
}

4. 并发或事务问题

若脚本采用多线程处理,可能出现同时生成相同编号的情况;未使用事务的话,部分导入失败会导致后续编号混乱。

修复:

  • 采用单线程处理CSV数据,避免并发生成编号;
  • 导入时使用SQL事务,若出现主键冲突则回滚并重试(或调整编号后重试)。

调试建议

  • 生成新编号后先输出到日志,检查是否有重复:
$newNums = @()
foreach ($row in $csvData) {
    # 生成新编号逻辑...
    $newNums += $newNumContrat
}
# 检测重复项
$duplicates = $newNums | Group-Object | Where-Object { $_.Count -gt 1 }
if ($duplicates) {
    Write-Warning "发现重复编号:$($duplicates.Name -join ', ')"
}
  • 查看SQL Server的主键冲突错误日志,定位具体重复的编号,反向排查生成逻辑问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:26:12