我想创建一个函数来创建一个唯一的随机id min
(最小数量), max
(最大数量),以及 tablename
(要检查的表的名称,以查看 rand()
函数已存在)。
我在其他文章中发现,不能将表名传递到函数中,因为函数不能执行动态sql,但可以将它们传递到存储过程中。我在stackoverflow上找到了许多例子,说明如何将表名传递到存储过程中,它们都归结为使用准备好的语句。
我创建了一个存储过程,如下所示:
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;
我得到这个错误:
# 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
我不知道发生了什么事。我在某个地方看到不能在存储过程中使用用户变量,但这似乎是不正确的,因为在stackoverflow上有很多例子,正确的解决方案就是这样做的。
对不起,我对mysql的理解水平很低。我确信我的代码充满了语法错误和糟糕的设计。我很感激能得到的任何帮助。我研究了很长一段时间,尝试了很多东西,但都没有结果。上面的代码部分是我所能得到的最接近的部分,并且产生的错误最少,但是它仍然不起作用。
谢谢您。
编辑:根据@barmar答案中的第二个示例,我将代码更改为:
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
它似乎已经解决了我最初的问题,但现在我得到了这个错误:
# 1327 - Undeclared variable: count_id
编辑:这是我修改的代码,以符合@slaakso的答案,并添加@barmar所说的关于使用@count\u id:
DELIMITER $$
CREATE DEFINER=`mjrinker`@`localhost` PROCEDURE `rand_id`(IN `min` BIGINT, IN `max` BIGINT, IN `tablename` VARCHAR(128) CHARSET utf8, OUT `uid` BIGINT)
BEGIN
SET @count_id = 1;
SET uid = 0;
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$$
DELIMITER ;
2条答案
按热度按时间mf98qq941#
你需要分配
@s
在分配uid
变量。你也错过了
SELECT
查询中的关键字。但实际上,您应该只准备一次语句,使用占位符,在使用
EXECUTE
.请注意,参数
EXECUTE
必须是用户变量,这就是我改变的原因uid
至@uid
在那里。然后在循环的末尾设置输出参数。您还需要使用用户变量
INTO @count_id
.iaqfqrcu2#
首先,使用随机数作为表的id是非常不寻常的。也许你应该考虑使用自动递增列。
如果您真的想使用随机数,请修复以下代码:
您应该使用值
uid
第一次运行查询时(如果没有它,它将为空,因此返回错误)。你失踪了
SELECT
在动态查询中“这个”
INTO count_id
“由于count\u id在动态sql中不可见(请使用@var
变量)最小值和最大值声明为int,但传递的参数超出int范围(-2147483648-2147483647)