我试图编写一个SQL功能,该函数在1000000和4294967295之间生成未使用的唯一ID。我需要数字值,因此UUID()都不是解决方案。听起来并不困难,但是由于某种原因,下面的代码在表上的插入插入中称为主键的值(当然不是自动iNcrement)。该声明就像 INSERT INTO table (id, content) VALUES ((SELECT getRandomID(0,0)), 'blabla bla');
(由于此类函数不允许默认值,因此我很快就将每个参数提交0,并将其设置为所需的值。)
呼叫一次,与插入或python代码分开,一切都很好。调用几次,不仅发生了一些奇怪的事情,而且服务器也可能挂在REPEAT
中。然后,该过程甚至不可能杀死/重新开始。我必须重新启动机器-.-它似乎也只有一些随机值为我准备,因为在调用一些呼叫后一次又一次出现相同的值,但我实际上认为内部rand()
将是外部rand()
的足够的启动/种子。从Python召集的循环在经过一些回合后开始悬挂,尽管我的测试中的第一个总是会产生有用的新ID,因此在第一轮后应该退出。wyh?好吧,表是空的...所以SELECT COUNT(*)...
返回0,这实际上是离开循环的信号……但事实并非如此。
有什么想法吗?我正在运行MariaDB 10.在SLES 12.2上的工作。这是导出的源代码:
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));