我尝试编写一个 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,因此应该在第一轮后退出。为什么?好吧,桌子是空的......所以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 ;