如何从MySQL存储过程中一次返回多行一个
我想返回一个在存储过程中动态创建的集合(为了简单起见,让我们假设该集合是偶数的列表,在循环内计算)。如何从MySQL存储过程中一次返回多行一个
我曾与一些数据库有一个SUSPEND
操作所添加的OUT
参数的当前值到结果集的过程中,像这样:
DELIMITER $
CREATE PROCEDURE EvenNumbers(
IN n INT, OUT NUM INT)
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET NUM = i;
SUSPEND; /* adds a row with a value 'i' for column NUM to the result set */
SET i = i+2;
END WHILE;
END$
DELIMITER ;
SUSPEND
是MySQL,但我的关键词假定它不做同样的事情,因为这不起作用(Error: Unexpected 'SUSPEND'
)。
那么,如何从MySQL中的存储过程中逐一返回一组行?
我知道你想要一个偶数生成器? 这是纯粹的MySQL,不使用存储过程。
首先,您需要使用以下查询生成很多关闭数字。 此查询生成1到10000条记录。
查询
SELECT
@row := @row + 1 AS ROW
FROM
(
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) row1
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) row2
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) row3
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) row4
CROSS JOIN (
SELECT @row := 0
) init_user_param
主查询。
查询
SELECT
*
FROM (
SELECT
@row := @row + 1 AS ROW
FROM
(
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) row1
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) row2
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) row3
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) row4
CROSS JOIN (
SELECT @row := 0
) init_user_param
)
ROWS
WHERE
ROWS.ROW BETWEEN 1 AND 10
AND
ROWS.ROW MOD 2 = 0
结果
row
--------
2
4
6
8
10
谢谢,但偶数只是一个例子。我正在寻找一个通用的解决方案,其中每个要返回的行由循环内的复杂计算确定。 – Alex
亚历克斯, 可以创建存储过程中的临时表(这是完全确定),存储该计算的结果并在完成计算后返回临时表的内容。因此,使用过程返回的正常结果集而不是OUT参数。
尽管看起来有点脆弱(不会丢掉临时表会导致后续调用中出现错误),但它还会污染表名称空间(我必须确保同一个表名不是在同一个数据库的任何地方使用)。如果MySQL具有该变量,我宁愿使用本地TABLE变量。 – Alex
如果使用“创建临时表”,则不会污染表名称空间。当您使用临时表时,它在连接内部是唯一的,并且直到连接关闭或直到您断开连接。为了安全起见,可以在创建临时表之前执行“删除临时表my_tmp”(如果存在),或者在过程结束时执行“删除临时表my_tmp”。 – slaakso
如果我使用“创建临时表”,那么在当前连接的上下文之外没有对表名称空间*的污染。我仍然必须确保我用于临时表的名称不会在其他地方使用。更重要的是,如果稍后某人决定在其他表中使用相同的名称,则只有在执行存储过程时才会显示错误,因此其他人都必须知道该决定。总体而言,临时表解决方案是程序中的抽象泄漏 - 程序不再是自包含的。 – Alex
没有“一次一个”的东西。存储过程运行完成并获得结果。如果你想将这些结果传送给你的客户,那就是你。 – tadman
@tadman我很好,将结果存储在某个地方,并在程序结束时将它们返回给客户端,但我不知道如何在MySQL中执行此操作(除非使用临时表,但听起来像是一种矫枉过正) 。 – Alex