我想创建一个将创建唯一的随机ID的函数。参数将简单地为min
(最小数),max
(最大数)和tablename
(表名,以检查{ {1}}函数已经存在。
通过其他文章,我发现您不能将表名传递给函数,因为函数不能执行动态SQL,但是您可以将它们传递给存储过程。我在StackOverflow上发现了很多有关如何将表名传递到存储过程中的示例,它们都归结为使用准备好的语句。
我已经创建了一个存储过程,如下所示:
rand()
每当我运行以下代码:
DELIMITER $$
CREATE DEFINER=`user`@`localhost` PROCEDURE `rand_id`(IN `min` INT, IN `max` INT, IN `tablename` VARCHAR(20) CHARSET utf8, OUT `uid` INT)
BEGIN
DECLARE count_id int;
SET count_id = 1;
SET @s = CONCAT('COUNT(`id`) INTO count_id FROM `', tablename, '` WHERE `id` = ', uid);
WHILE count_id > 0 DO
SET uid = FLOOR(rand() * max + min);
PREPARE stmt from @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END WHILE;
END$$
DELIMITER ;
我收到此错误:
CALL rand_id(1000000000, 9999999999, 'test', @id);
SELECT @id;
我不知所措。我在某个地方看到您不能在存储过程中使用用户变量,但这似乎是不正确的,因为在StackOverflow上有很多示例,其中正确的解决方案正是这样做的。
很抱歉,我对MySQL的了解不高。我确定我的代码充满语法错误和不良的设计。感谢您能提供的任何帮助。我研究了很长时间,尝试了许多尝试,但无济于事。上面的代码部分是我所能获得的最接近的代码,并且产生的错误最少,但仍然无法正常工作。
谢谢。
编辑:根据@Barmar回答中的第二个示例,我将代码更改为如下形式:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
似乎已经解决了我最初的问题,但是现在我收到了这个错误:
BEGIN
DECLARE count_id int;
SET count_id = 1;
SET @s = CONCAT('SELECT COUNT(`id`) INTO count_id FROM `', tablename, '` WHERE `id` = ?');
PREPARE stmt from @s;
WHILE count_id > 0 DO
SET @uid = FLOOR(rand() * max + min);
EXECUTE stmt USING @uid;
END WHILE;
DEALLOCATE PREPARE stmt;
SET uid = @uid;
END
编辑:这是我的代码更改为适合@slaakso的答案,并添加了@Barmar关于使用@count_id的内容:
#1327 - Undeclared variable: count_id
答案 0 :(得分:1)
在分配@s
变量之后,您需要分配uid
。
您在查询中还缺少SELECT
关键字。
SET @count_id = 1
WHILE @count_id > 0 DO
SET uid = FLOOR(rand() * max + min);
SET @s = CONCAT('SELECT COUNT(`id`) INTO @count_id FROM `', tablename, '` WHERE `id` = ', uid);
PREPARE stmt from @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END WHILE;
但是您实际上应该只使用占位符准备一次语句,该占位符是在使用EXECUTE
时填写的。
SET @count_id = 1
SET @s = CONCAT('SELECT COUNT(`id`) INTO @count_id FROM `', tablename, '` WHERE `id` = ?');
PREPARE stmt from @s;
WHILE @count_id > 0 DO
SET @uid = FLOOR(rand() * max + min);
EXECUTE stmt USING @uid;
END WHILE;
DEALLOCATE PREPARE stmt;
SET uid = @uid;
请注意,EXECUTE
的参数必须是用户变量,这就是为什么我在这里将uid
更改为@uid
的原因。然后,在循环结束时设置输出参数。
您还需要为INTO @count_id
使用用户变量。
答案 1 :(得分:0)
首先,使用随机数作为表的ID是非常不寻常的。 Mabye,您应该考虑使用AUTO_INCREMENT列。
如果您真的想使用随机数,请修复以下代码:
uid
的值
(如果没有它,将为NULL,因此会出现错误)。 SELECT
INTO count_id
”语法不起作用,因为count_id在动态SQL中不可见(改为使用@var
变量)