将重复的varchars更新为SQL数据库中的唯一

3 sql database unique duplicates

我需要更改数据库以在表列上添加唯一约束,但其中的VARCHAR数据不是唯一的.

如何通过在现有数据末尾添加序号来更新这些重复记录,以使每个值都是唯一的?

例如,我想将'name'更改为'name1','name2','name3'

jha*_*amm 7

以下是使用sql的MS SQL SERVER风格的2个示例.

设置示例:

create table test (id int identity primary key, val varchar(20) )
    --id is a pk for the cursor so it can update using "where current of"

-- name a is not duplicated
-- name b is duplicated 3 times
-- name c is duplicated 2 times

insert test values('name a')
insert test values('name b')
insert test values('name c')
insert test values('name b')
insert test values('name b')
insert test values('name c')
Run Code Online (Sandbox Code Playgroud)

Sql 2005\2008 :(计算表表达式)

begin tran; -- Computed table expressions require the statement prior to end with ;

with cte(val,row) as (

    select val, row_number() over (partition by val order by val) row
    --partiton is important. it resets the row_number on a new val
    from test 
    where val in ( -- only return values that are duplicated
        select val
        from test
        group by val
        having count(val)>1
    )
)
update cte set val = val + ltrim(str(row))
--ltrim(str(row)) = converting the int to a string and removing the padding from the str command.

select * from test

rollback
Run Code Online (Sandbox Code Playgroud)

Sql 2000 :(光标示例)

begin tran

declare @row int, @last varchar(20), @current varchar(20)
set @last = ''
declare dupes cursor
    for
    select val 
    from test 
    where val in ( -- only return values that are duplicated
        select val
        from test
        group by val
        having count(val)>1
    )
    order by val

    for update of val

open dupes
fetch next from dupes into @current
while @@fetch_status = 0
begin
    --new set of dupes, like the partition by in the 2005 example
    if @last != @current
        set @row = 1

    update test
        --@last is being set during the update statement
        set val = val + ltrim(str(@row)), @last = val
        where current of dupes

    set @row = @row + 1

    fetch next from dupes into @current
end
close dupes
deallocate dupes

select * from test

rollback
Run Code Online (Sandbox Code Playgroud)

我回滚了每个更新,因为我的脚本文件包含两个示例.这使我可以在不重置表格中的行的情况下测试功能.