Обновите дубликаты varchars, чтобы они были уникальными в базе данных SQL - PullRequest
3 голосов
/ 28 апреля 2009

Мне нужно изменить базу данных, чтобы добавить уникальное ограничение для столбца таблицы, но данные VARCHAR в нем не уникальны.

Как я могу обновить эти дубликаты записей, чтобы каждое значение было уникальным путем добавления порядкового номера в конце существующих данных?

например. Я хотел бы изменить «имя» на «имя1», «имя2», «имя3»

Ответы [ 4 ]

7 голосов
/ 09 мая 2009

Вот 2 примера использования MS SQL SERVER в SQL.

Пример установки:

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

Я откатил каждое из обновлений, потому что мой файл сценария содержит оба примера. Это позволило мне проверить функциональность без сброса строк в таблице.

1 голос
/ 28 апреля 2009

Открыть курсор на столе, упорядоченный по этому столбцу. Сохраните предыдущую переменную значения, инициализированную нулем, и индексную переменную, инициализированную 0. Если текущее значение = предыдущее значение, увеличьте индекс и добавьте индекс к значению поля. если текущее значение <> предыдущего значения, сбросьте индекс на 0 и сохраните значение поля как есть. Установите предыдущее значение переменной = текущее значение. Перейдите к следующему ряду и повторите.

0 голосов
/ 28 апреля 2009

Вы можете добавить еще один столбец к нему ... как

update mytable set mycolumn = concat(mycolumn, id) 
            where id in (<select duplicate records>);

заменить идентификатор на любой столбец, который делает mycolumn уникальным

0 голосов
/ 28 апреля 2009

Какую базу данных вы используете?

В Oracle есть:

NOVALIDATE Проверяет изменения, но не проверяет данные, ранее существовавшие в таблице

Пример:

ALTER TABLE <table_name> ENABLE NOVALIDATE UNIQUE;

Если вы не используете Oracle, проверьте ссылку на SQL для вашей соответствующей базы данных.

...