如何动态更新SQL重复行值为唯一并避免新重复?
解决SQL更新重复行后产生新重复的问题
问题根源
原方案按原始Name+ID分区生成行号,仅处理完全相同的Name重复。但当数据中已存在带数字后缀的同名变体(比如Duplicate (2))时,更新后的行(比如把第二个Duplicate改成Duplicate (2))会和已有的变体重复,导致新的唯一性冲突。
解决方案思路
核心是先提取每个Name的基础名称(去掉末尾的(数字)后缀),再按「基础名称+ID」分组,给组内每行分配连续唯一的行号,最后基于行号生成新的唯一Name。这样不管原始数据有没有带数字后缀,都会统一归组编号,彻底避免更新后的重复。
修正后的SQL代码
CREATE TABLE #temp (name nvarchar(100), ID uniqueidentifier) INSERT INTO #temp (Name, ID) VALUES ('Duplicate', '32208C09-C0C3-408C-AB60-273811722194') INSERT INTO #temp (Name, ID) VALUES ('Duplicate', '32208C09-C0C3-408C-AB60-273811722194') INSERT INTO #temp (Name, ID) VALUES ('Duplicate (2)', '32208C09-C0C3-408C-AB60-273811722194') ;WITH cte AS ( SELECT Name, -- 提取基础名称:自动识别并去除末尾的 "(数字)" 格式后缀 TRIM(LEFT(Name, PATINDEX('%([0-9])%', Name + ' (0)') - 2)) AS BaseName, -- 按基础名称+ID分组,生成连续行号 ROW_NUMBER() OVER (PARTITION BY TRIM(LEFT(Name, PATINDEX('%([0-9])%', Name + ' (0)') - 2)), ID ORDER BY Name) AS RowNum FROM #temp ) UPDATE cte SET Name = CASE WHEN RowNum = 1 THEN BaseName -- 保留组内第一条的基础名称 ELSE CONCAT(BaseName, ' (', RowNum, ')') -- 后续行拼接行号后缀 END SELECT * FROM #temp DROP TABLE #temp
执行结果
更新后的数据表内容为:
| Name | ID |
|---|---|
| Duplicate | 32208C09-C0C3-408C-AB60-273811722194 |
| Duplicate (2) | 32208C09-C0C3-408C-AB60-273811722194 |
| Duplicate (3) | 32208C09-C0C3-408C-AB60-273811722194 |
所有Name均唯一,符合要求。
关键细节说明
- 基础名称提取逻辑:通过
PATINDEX('%([0-9])%', Name + ' (0)')定位末尾数字后缀的起始位置,再截取前面的内容并去除空格。即使原始Name没有数字后缀,Name + ' (0)'也能保证正则匹配到虚拟后缀,不会影响基础名称的提取。 - 分组逻辑:按「基础名称+ID」分组,确保同一业务实体(相同ID+核心名称)的所有行被统一编号,从根源避免重复。
内容的提问来源于stack exchange,提问作者Carter W
相关产品推荐
相关产品推荐

