首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL:获取随机唯一整数ID

问MySQL:获取随机唯一整数ID
EN

Stack Overflow用户
提问于 2017-11-22 22:20:48
回答 1查看 1.1K关注 0票数 0

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

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

有什么想法吗?我在SLES12.2上运行MariaDB 10.thing。以下是导出的源代码:

代码语言:javascript
复制
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 ;
EN

回答 1

Stack Overflow用户

发布于 2017-11-23 08:49:59

一个小小的改进:

代码语言:javascript
复制
    SELECT COUNT(*) INTO i FROM `table` WHERE `id` = rnd;    
UNTIL i = 0 END REPEAT r; 

-->

代码语言:javascript
复制
UNTIL NOT EXISTS( SELECT 1 FROM `table` WHERE id = rnd ) REPEAT r; 

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

代码语言:javascript
复制
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)

所以简化为

代码语言:javascript
复制
    SET rnd = FLOOR(rangeStart + RAND() * (rangeEnd - rangeStart));

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

代码语言:javascript
复制
    SET rnd = FLOOR(rangeStart + RAND() * (rangeEnd - rangeStart + 1));
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47436994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档