我需要更改数据库以在表列上添加唯一约束,但其中的 VARCHAR 数据不是唯一的。
如何通过在现有数据的末尾添加序列号来更新这些重复记录,以便每个值都是唯一的?
例如,我想将 'name' 更改为 'name1'、'name2'、'name3'
我需要更改数据库以在表列上添加唯一约束,但其中的 VARCHAR 数据不是唯一的。
如何通过在现有数据的末尾添加序列号来更新这些重复记录,以便每个值都是唯一的?
例如,我想将 'name' 更改为 'name1'、'name2'、'name3'
以下是使用 MS SQL SERVER 风格的 sql 的 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')
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
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
我回滚了每个更新,因为我的脚本文件包含这两个示例。这使我可以在不重置表格行的情况下测试功能。
在表上打开一个游标,按该列排序。保留前一个值变量,初始化为 null,索引变量初始化为 0。如果当前值 = 前一个值,则递增索引并将索引附加到字段值。如果当前值 <> 前一个值,则将索引重置为 0 并保持字段值不变。设置前一个值变量 = 当前值。移动到下一行并重复。
你用的是什么数据库?
在Oracle中有一个:
NOVALIDATE 验证更改但不验证表中先前存在的数据
例子:
ALTER TABLE <table_name> ENABLE NOVALIDATE UNIQUE;
如果您不使用 Oracle,请检查相应数据库的 SQL 参考。
您可以向其中添加另一列...例如
update mytable set mycolumn = concat(mycolumn, id)
where id in (<select duplicate records>);
将 id 替换为使 mycolumn 唯一的任何列