2

我有一个较旧的数据库(出于一些非常可疑和晦涩的原因,我不想在这里过多地讨论主题)我想随机化或随机化主键。

我现在在 Mysql 数据库表中有自动增量字段。

我没有很多关系,那些存在的没有定义为外键。不需要保留这些关系。

我正在寻找的只是获取主键的当前值并将其替换为以下随机值:

ID := new(ID)

新函数从具有 1:1 匹配的所有 OLD id 集合中返回一个值。例如

2 := 3
3 := 2

但不是

2 := 3
3 := 3

有没有办法通过(理想情况下)每个表的单个 SQL 查询来更改数据库中的数据?

编辑:我没有非常严格的要求。如果有帮助,考虑对数据库进行独占访问,包括来回更改对主键的约束,例如更改表、执行操作、将表更改为以前的模式。也可以为新的(或旧的)PK 值添加另一列。

4

3 回答 3

5

只是过程的一个缩影。创建两个临时表

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 ;

将不同顺序的值复制id到两个表中(随机在第二个表中):

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-Fiddle中测试

于 2012-12-28T01:42:47.980 回答
3

这是一种按表格顺序创建您的 id 列表的技术,以及从 1 开始的序列号,它还以随机顺序创建您的 id 列表,以及从 1 开始的序列号。然后它根据与序号相匹配。

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 回答