我有一个大约20k行的小表。在该表中有一个名为random_uid(INT NOT NULL
)的列。我想用一个随机的唯一数字更新所有20k行。
由于我的表很小,我认为不需要使用字符串或UUID,所以我使用了
SELECT FLOOR(RAND() * 100000000) AS random_num
FROM table1
WHERE "random_num" NOT IN (SELECT random_uid FROM table1)
LIMIT 1;
我的问题是我不能从同一个表中更新和选择,所以我在创建UPDATE查询时遇到了麻烦。
- 编辑:* 我对上面的随机性没有问题,因为我不是为了任何安全目的而使用它,只是为了为每一行创建 * 唯一的 * id,而不仅仅是递增。因为我使用select来验证另一行中不存在相同的数字,所以我不能使用
UPDATE
,这就是问题所在。
7条答案
按热度按时间smdncfj31#
对200万条记录进行测试,100次迭代。测试成功。
mrzz3bfm2#
可以使用update触发器修改现有行,使用insert触发器为新行生成随机数。在触发器主体中,生成一个随机数,并检查它是否已经存在于表中。你可以在一个循环中完成它,一旦找到一个新的(唯一的)数字,就离开这个循环。
UPDATE触发器
您可以使用以下命令更新表中的所有行:
注意,列
random_num
必须是可空的。但它可以是UNIQUE
。所以你可以把它定义为random_num int null unique
。由于您只需要执行此步骤一次,因此现在可以放下该触发器。
INSERT触发器
INSERT触发器具有相同的主体。插入新行时,不需要设置
random_num
列。触发器会搞定的它甚至可以很好地使用批量插入:演示:http://rextester.com/ZIDG57947
请注意,我在演示中使用
FLOOR(RAND() * 10)
来演示小范围内的唯一性。但是-您不应该尝试插入比可能的唯一数字的数量更多的行:-)对于20K行和100M个可能的唯一数字,循环将需要每行1.0002次(平均)迭代。
vwhgwdsa3#
更新2023-06-08
如果你对UUID满意,你可以在mysql 8上轻松地完成这一点:
相应地调整where子句以定位要更新的行。我提供id=23只是为了最大限度地减少有人通过复制粘贴无意中更新数据库中所有行的风险。
原创帖子
借用@BillKarwin,UUID提供了一种在数据库中获取随机和唯一字段的方法,Mysql 8有一些部分但完全可行的支持。
要存储它们,您的字段需要是VARCHAR(37)。确保您也已为该字段指定了唯一约束。有更有效的方法来存储它们,将它们打包成16字节大小的二进制文件,但这超出了本文的范围-网上有其他文章解释如何打包uuid。
在上述查询之后,每个uuid_field都有一个通用的唯一id。您还需要有一个触发器,在插入时填充列的值。假设字段名为'uuid_field'并且是一个varchar,下面是触发器:
rfbsl7qr4#
您可以生成前N个整数的随机序列,并使用该序列更新表(其中N是表中的行数)。
说明:
构建N个数字的随机序列。我们使用一个变量,它对每一行都递增。
(SELECT @rn1:=-1) as t3 cross join
等价于set @rn1:=-1;
我们使用交叉连接技巧将两个语句放在一行中。因此,这生成了从0到N-1的序列,并使用order by Rand()
对其进行加扰我们用一个行号来增加这个表
我们以类似的方式用行号增加原始表:
我们使用行号连接这两个部分:
我们有效地构建了一个表,其中一列包含id,另一列包含问题中提到的random_uid(称为rnd_id)。此时,我们可以继续更新,用新的rnd_id表扩充表,并将原始表(这里称为random_id)中的random_uid设置为等于rnd_id:
关于在同一个表中使用update和select的麻烦,我认为诀窍是为表使用不同的别名。参考MySql - Update table using select statment from same table
这解决了为所有表填充random_uid的问题。在我的例子中,当我添加一行时,我只是添加一个random_uid,它等于表中元素的数量,所以N(因为我从0开始)。这在我的情况下已经足够好了,但一般情况下并不是这样,这取决于您的限制。
nhaq1z215#
如果你有一个唯一的ID,你可以这样做:
首先,根据id的MD5字符串和当前完整的日期时间创建一个随机值。由于MD5不是无限的,因此您可以从两个不同的字符串获得相同的散列;您可以通过将原始id连接到MD5字符串来解决它,因为该id是唯一的。
3htmauhk6#
可能最简单的方法是重复运行这个查询:
在每轮之间,您可以调用:
看看有没有重复的
如果你在MySQL Workbench中工作,你可以创建一个临时过程来为你做这件事,就像这样:
这实际上只是一种蛮力的方法,有各种各样的方法可以优化性能,但这可以快速完成工作。我真的会建议用另一种方式来做这件事,例如。的UUID。
frebpwbc7#
这里有一个简单的方法。我用512行填充了一个测试表,然后这样做:
这些数字现在随机分配给各行,但每行都有一个唯一的值。
但是,在为随后插入的行赋值时,它不会是随机的。