3

テーブルの列に一意の制約を追加するようにデータベースを変更する必要がありますが、その中の VARCHAR データは一意ではありません。

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

たとえば、'name' を 'name1'、'name2'、'name3' に変更したい

4

4 に答える 4

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')

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

スクリプト ファイルには両方の例が含まれているため、それぞれの更新をロールバックしました。これにより、テーブルの行をリセットせずに機能をテストできました。

于 2009-05-09T04:18:56.810 に答える
1

その列で並べ替えられたテーブルでカーソルを開きます。null に初期化された前の値変数と、0 に初期化されたインデックス変数を保持します。現在の値 = 前の値の場合、インデックスをインクリメントし、インデックスをフィールド値に追加します。現在の値 <> 前の値の場合、インデックスを 0 にリセットし、フィールド値をそのまま保持します。以前の値の変数 = 現在の値を設定します。次の行に移動して繰り返します。

于 2009-04-28T17:32:02.997 に答える
0

どのデータベースを使用していますか?

Oracleには次のものがあります。

NOVALIDATE 変更を検証しますが、テーブルに以前存在していたデータは検証しません

例:

ALTER TABLE <table_name> ENABLE NOVALIDATE UNIQUE;

Oracle を使用していない場合は、それぞれのデータベースの SQL リファレンスを確認してください。

于 2009-04-28T05:21:51.910 に答える
0

それに別の列を追加できます...のように

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

id を mycolumn を一意にする列に置き換えます

于 2009-04-28T05:46:59.227 に答える