2

私は古いデータベースを持っていますが、そのために(ここであまり話題にしたくない、本当に疑わしくてあいまいな理由で)主キーをランダム化またはシャッフルしたいと思います。

現在、Mysqlデータベーステーブルに自動インクリメントフィールドがあります。

私には多くの関係はありません。存在する関係は外部キーとして定義されていません。関係を保持する必要はありません。

私が探しているのは、主キーの現在の値を取得し、次のようなものからランダムな値に置き換えることだけです。

ID := new(ID)

新しい関数が、1:1の一致を持つすべてのOLDIDのセットから値を返す場合。例えば

2 := 3
3 := 2

だがしかし

2 := 3
3 := 3

(理想的には)テーブルごとに1つのSQLクエリを使用してデータベース内のデータを変更する方法はありますか?

編集:私は本当に厳しい要件はありません。テーブルの変更、操作の実行、テーブルの前のスキーマへの変更など、主キーの制約を前後に変更するなど、役立つ場合はデータベースへの排他的アクセスを検討してください。新しい(または古い)PK値に別の列を追加することもできます。

4

3 に答える 3

5

手順のほんの一部です。2 つの一時テーブルを作成する

CREATE TABLE temp_old
( ai INT NOT NULL AUTO_INCREMENT
, id INT NOT NULL
, PRIMARY KEY (ai)
, INDEX old_idx (id, ai)
) ENGINE = InnoDB ;

CREATE TABLE temp_new
( ai INT NOT NULL AUTO_INCREMENT
, id INT NOT NULL
, PRIMARY KEY (ai)
, INDEX new_idx (id, ai)
) ENGINE = InnoDB ;

値を異なる順序で 2 つのテーブルにコピーしidます (2 番目のテーブルでランダムに):

INSERT INTO temp_old
  (id)
SELECT id
FROM tableX 
ORDER BY id ;

INSERT INTO temp_new
  (id)
SELECT id
FROM tableX 
ORDER BY RAND() ;

次に、主キーを削除します。

ALTER TABLE tableX
  DROP PRIMARY KEY ; 

実際のUPDATEステートメントを実行するには:

UPDATE tableX AS t
  JOIN temp_old AS o
    ON o.id = t.id
  JOIN temp_new AS n
    ON n.ai = o.ai
SET t.id = n.id ;

次に、主キーを再作成し、一時テーブルを削除します。

ALTER TABLE tableX
  ADD PRIMARY KEY (id) ; 

DROP TABLE temp_old ;
DROP TABLE temp_new ;

SQLフィドルでテスト済み

于 2012-12-28T01:42:47.980 に答える
3

これは、ID のリストをテーブル順に作成し、1 からの連続番号を付けて作成する手法です。また、ID のリストをランダムな順序で作成し、1 からの連続番号を付けます。次に、に基づいて ID を更新します。連番に合わせます。

order by rand() のパフォーマンスに問題があります (それはランダム性です)。

キーがすでに 1 から連続している場合は、これを単純化できます。

Update
  Test as t
    Inner Join (
    Select 
      @rownum2 := @rownum2 + 1 as rank,
      t2.id
    From
      Test t2,
      (Select @rownum2:= 0) a1
  ) as o on t.id = o.id
    Inner Join (
      Select
        @rownum := @rownum + 1 as rank,
        t3.id
      From
        (Select id from Test order by Rand()) t3,
        (Select @rownum:= 0) a2
  ) as n on o.rank = n.rank
Set
  t.id = n.id

http://sqlfiddle.com/#!2/3f354/1

于 2012-12-28T01:35:13.107 に答える
1

すべての ID を含む一時テーブルを作成するストアド プロシージャを作成し、各レコードをループして ID を一時テーブルの ID に置き換え、その ID を一時テーブルから削除することができます。ただし、あなたが話していることを単一のクエリで実行する方法があるとは思いません。

于 2012-12-28T01:07:01.753 に答える