MySQL:获取随机唯一整数ID

标签 mysql random mariadb mysql-function

我尝试编写一个 SQL 函数,生成一个范围在 1000000 到 4294967295 之间的未使用的唯一 ID。我需要数值,因此类似 UUID() 不是一个解决方案。这听起来并不困难,但由于某种原因,当在表上的 INSERT 语句中调用下面的代码作为主键的值(当然不是 auto_increment)时,下面的代码不起作用。该语句类似于 INSERT INTO table (id, content) VALUES ((SELECT getRandomID(0,0)), 'blabla bla'); (由于此类函数中不允许使用默认值,因此我很快为每个参数提交 0 并在函数中将其设置为所需的值。)

调用一次并与 INSERT 或 Python 代码分离,一切都很好。调用几次后,会发生一些奇怪的事情,不仅整个过程而且服务器也可能会在 REPEAT 内挂起。 。该进程甚至无法终止/重新启动;我必须重新启动机器-.- 它似乎也只为我准备了一些随机值,因为在一些调用后相同的值一次又一次出现,尽管我实际上认为内部 rand()对于外部rand()来说将是一个足够的开始/种子。 从 Python 调用,循环在几轮后开始挂起,尽管我的测试中的第一个循环总是产生一个有用的新 ID,因此应该在第一轮后退出。为什么?好吧, table 是空的......所以 SELECT COUNT(*)...返回 0,这实际上是离开循环的信号……但事实并非如此。

有什么想法吗? 我正在 SLES 12.2 上运行 MariaDB 10.something。这是导出的源代码:

DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `getRandomID`(`rangeStart` BIGINT UNSIGNED, `rangeEnd` BIGINT UNSIGNED) RETURNS bigint(20) unsigned
READS SQL DATA
BEGIN
    DECLARE rnd BIGINT unsigned; 
    DECLARE i BIGINT unsigned; 

    IF rangeStart is null OR rangeStart < 1 THEN
        SET rangeStart = 1000000;
    END IF;
    IF rangeEnd is null OR rangeEnd < 1 THEN
        SET rangeEnd = 4294967295; 
    END IF; 

    SET i = 0;

    r: REPEAT
        SET rnd = FLOOR(rangeStart + RAND(RAND(FLOOR(1 + rand() * 1000000000))*10) * (rangeEnd - rangeStart));
        SELECT COUNT(*) INTO i FROM `table` WHERE `id` = rnd;    
    UNTIL i = 0 END REPEAT r; 

    RETURN rnd;
END$$
DELIMITER ;

最佳答案

略有改进:

    SELECT COUNT(*) INTO i FROM `table` WHERE `id` = rnd;    
UNTIL i = 0 END REPEAT r; 

-->

UNTIL NOT EXISTS( SELECT 1 FROM `table` WHERE id = rnd ) REPEAT r; 

不要向 RAND 传递任何参数——这是为了建立可重复的随机数序列。

mysql> SELECT RAND(123), RAND(123), RAND(), RAND()\G
*************************** 1. row ***************************
RAND(123): 0.9277428611440052
RAND(123): 0.9277428611440052
   RAND(): 0.5645420109522921
   RAND(): 0.12561983719991504
1 row in set (0.00 sec)

所以简化为

    SET rnd = FLOOR(rangeStart + RAND() * (rangeEnd - rangeStart));

如果您想在可能的输出中包含 rangeEnd,请添加 1:

    SET rnd = FLOOR(rangeStart + RAND() * (rangeEnd - rangeStart + 1));

关于MySQL:获取随机唯一整数ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47436994/

相关文章:

mysql - 将数据插入 MySQL/MariaDB 的最快、最简单的方法是什么?

mysql - Heroku (Postgres) 上的 Where 子句中断,但在本地运行良好 (MySQL)

mysql - 在 mySQL 上统计上一年

php - 在HTML FORM + IMAGE UPLOAD + PHP + MYSQL中选择

algorithm - 生成具有固定位数的随机数的最有效方法

java - 获取一个带有偏差的范围内的随机数

mysql - 自定义 docker 官方 mariadb 镜像

php - 使用 PHP 从数据库中获取与查询匹配的所有条目

Swift 在 0 和 1 之间随机 float

mysql - 飞行路线 | MariaDb - 无法执行条件 block