如何从MySQL存储过程中一次返回多行一个

如何从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中的存储过程中逐一返回一组行?

+0

没有“一次一个”的东西。存储过程运行完成并获得结果。如果你想将这些结果传送给你的客户,那就是你。 – tadman

+0

@tadman我很好,将结果存储在某个地方,并在程序结束时将它们返回给客户端,但我不知道如何在MySQL中执行此操作(除非使用临时表,但听起来像是一种矫枉过正) 。 – Alex

我知道你想要一个偶数生成器? 这是纯粹的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 
+0

谢谢,但偶数只是一个例子。我正在寻找一个通用的解决方案,其中每个要返回的行由循环内的复杂计算确定。 – Alex

亚历克斯, 可以创建存储过程中的临时表(这是完全确定),存储该计算的结果并在完成计算后返回临时表的内容。因此,使用过程返回的正常结果集而不是OUT参数。

+0

尽管看起来有点脆弱(不会丢掉临时表会导致后续调用中出现错误),但它还会污染表名称空间(我必须确保同一个表名不是在同一个数据库的任何地方使用)。如果MySQL具有该变量,我宁愿使用本地TABLE变量。 – Alex

+0

如果使用“创建临时表”,则不会污染表名称空间。当您使用临时表时,它在连接内部是唯一的,并且直到连接关闭或直到您断开连接。为了安全起见,可以在创建临时表之前执行“删除临时表my_tmp”(如果存在),或者在过程结束时执行“删除临时表my_tmp”。 – slaakso

+0

如果我使用“创建临时表”,那么在当前连接的上下文之外没有对表名称空间*的污染。我仍然必须确保我用于临时表的名称不会在其他地方使用。更重要的是,如果稍后某人决定在其他表中使用相同的名称,则只有在执行存储过程时才会显示错误,因此其他人都必须知道该决定。总体而言,临时表解决方案是程序中的抽象泄漏 - 程序不再是自包含的。 – Alex