2009-04-28 7 views
3

テーブルの列に一意制約を追加するためにデータベースを変更する必要がありますが、その中のVARCHARデータは一意ではありません。重複するvarcharsをSQLデータベース内でユニークに更新する

これらの重複レコードを更新して、既存のデータの末尾に連番を追加して各値を一意にするにはどうすればよいですか?

「名前」を「名前1」、「名前2」、「名前3」に変更したい

答えて

0

どのデータベースをお使いですか? Oracle

があります:

NOVALIDATEは、変更内容を検証しますが、テーブル内の既存の以前のデータを検証しません

例:

ALTER TABLE <table_name> ENABLE NOVALIDATE UNIQUE; 

はあなたがSQLを確認するOracleを使用していない場合それぞれのデータベースの参照。

+0

私たちはFrontBase(SQL92準拠)を使用しています 私は既存のデータを検証して更新します。 –

+0

-1、これは彼が求めているものではありません。 –

+0

私はそれが彼が尋ねたものではないことを知っていますが、彼がFrontBaseを使っていると言っている前にそれを書きました。しかし、原則は同じです:データベースはNOVALIDATE節と同様の何かを持つことができます。 CONSTRAINTの種類が変更されたと思われる場合は、PRIMARY KEYを気にしないでください。 – Azder

0

あなたはそれに別の列を追加することができます...のような

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

MYCOLUMNユニーク

1

開き、その列によって注文テーブルの上にカーソルを、作るものは何でもコラムでIDを交換してください。以前の値変数をnullに初期化し、インデックス変数を0に初期化します。現在の値が前の値の場合は、インデックスを増分してインデックスをフィールド値に追加します。現在の値<>前の値の場合は、インデックスを0にリセットし、フィールド値をそのままにします。以前の値の変数=現在の値を設定します。次の行に移動し、繰り返します。

7

ここには、SQLのMS SQL SERVERフレーバを使用した2つの例があります。

設定例:2008 \ 2005

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:(コンピュータテーブル式)が

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 
     [email protected] 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 

私は背中の各圧延しました私のスクリプトファイルには両方の例が含まれているので、更新してください。これにより、テーブルの行をリセットせずに機能をテストすることができました。

関連する問題