MySQL存储过程返回多个记录集

7

我已在我的数据库(MySQL)中创建了一些存储过程,如下所示。

存储过程1

CREATE PROCEDURE sp_Name1(
    param1,
    param2,
    ...... 
)
BEGIN
   .....
   some code
   IF cond THEN 
       call sp_Name2  //Calling 2nd procedure from here.

       Update SomeTable .....

       SELECT '1' As Result;
   END IF
END

存储过程 2

CREATE PROCEDURE sp_Name2(
    param1,
    param2,
    ...... 
)
BEGIN
   .....
   some code
   IF cond THEN 
       SELECT '2' As Result;

       SELECT '3' As Result;
   END IF
END

现在我将调用我的第一个存储过程,如下所示:

Call sp_Name1(param1, param2, ... );

在MySQL Workbench中,我得到了4个结果集。其中2个来自sp_Name2,第三个是sp_Name1中的更新语句,第四个是sp_Name1中的选择语句。我只需要最后一个结果集。有时结果顺序会按照预期顺序出现,这意味着结果可能会像Result 1、Result 2、Result 4、Result 3这样出现(在这种情况下,我无法判断哪个结果集对我有用,因为最后一个结果集可能已经改变)。
如何抑制不需要的结果集?
编辑:我有使用案例,以便您更好地理解。
CREATE PROCEDURE sp_LoginUser( IN Username  varchar(50) , IN password varchar(50) )
BEGIN
    IF EXISTS( SELECT 1 FROM Users where name = UserName and Pwd = password)
       SET userid = 0;
       SET loginid = 0;
       SELECT userid INTO userid
       FROM users
       WHERE name = UserName and Pwd = password;
       IF userid > 0 THEN
           CALL sp_Login(userid);
           SET loginid = LAST_INSERT_ID();         
       END IF;
       //only this result i am expecting.
       IF loginid > 0 THEN
           SELECT userid as userid, loginid AS loginid;
       ELSE
           SELECT 0 userid, 0 loginid;
       END IF;
    END IF;
END

CREATE PROCEDURE sp_Login( IN Userid int )
BEGIN
    INSERT Logins ( userid, datetime )
    VALUES ( Userid, now() );

    SELECT LAST_INSERT_ID() AS loginid;
END

现在,当我的用户在登录页面输入用户名和密码并请求登录时,我需要在服务器上调用sp_LoginUser()。在许多情况下,我必须单独调用sp_Login()。

在上述情况下,我可以将一个参数(例如loginid)设置为sp_Login()过程中的INOUT,并将LAST_INSERT_ID()分配给它,删除SELECT语句并在sp_LoginUser()中检索。

但是,当我需要单独调用sp_Login()时,我必须在我的代码中声明一些变量来检索值。


1
请问您能否提供一些有意义的示例代码,以便我们运行并重现您所面临的问题?您发布的代码完全含糊不清。 - Rachcha
6个回答

9
如果您不想要那些结果集,请不要选择它们。

4
当你在存储过程中执行select语句时,结果集将返回给客户端。详细内容请参考: http://dev.mysql.com/doc/refman/5.5/en/faqs-stored-procs.html#qandaitem-B-4-1-14
CREATE PROCEDURE sp_LoginUser( IN Username  varchar(50) , IN password varchar(50) )
BEGIN
    --put the resultset into a variable so it don't return back
    DECLARE doesUserExist BOOL;
    SELECT EXISTS( SELECT 1 FROM Users where name = UserName and Pwd = password ) INTO doesUserExist;
    IF doesUserExist
       SET userid = 0;
       SET loginid = 0;
       SELECT userid INTO userid
       FROM users
       WHERE name = UserName and Pwd = password;
       IF userid > 0 THEN
           -- call a function instead of a procedure so you don't need to call last_insert_id again
           SET loginid = sp_Login(userid);
       END IF;
       //only this result i am expecting.
       IF loginid > 0 THEN
           SELECT userid as userid, loginid AS loginid;
       ELSE
           SELECT 0 userid, 0 loginid;
       END IF;
    END IF;
END
-- this is now a function so it can return what you need
CREATE FUNCTION sp_Login(Userid int) 
RETURNS INTEGER
BEGIN
    INSERT Logins ( userid, datetime )
    VALUES ( Userid, now() );

    SET loginid = LAST_INSERT_ID();
    RETURN loginid;
END

3

2
为什么要使用存储过程?你可以用普通的SQL语句完成这个任务:
SET @previous := LAST_INSERT_ID();

INSERT INTO Logins ( userid, datetime )
SELECT Userid, now()
FROM users
WHERE name = UserName
and Pwd = password;

SELECT *
FROM Logins
WHERE ID = LAST_INSERT_ID()
AND ID != @previous;

如果用户名/密码正确,您的行集将包含登录的行 - 您可以将其与用户表连接以获取所有用户数据。
如果用户名/密码不正确,则会有一个空的行集。
FYI,如果没有先前的插入,则LAST_INSERT_ID()返回0
存储过程是实现SQL的最不受欢迎的方式,特别是因为它们是最不可移植的方式(还有其他好的理由);如果您可以使用普通的SQL实现,那么这是更好的选择。虽然这个SQL并不完全可移植,但它可以相对容易地转换,因为大多数数据库具有与MySQL类似的函数和特性。

2

我不确定为什么您在sp_Login中选择了LAST_INSERT_ID(),然后又在sp_LoginUser中使用它?

如果您需要从sp_Login返回LAST_INSERT_ID(),则需要将其分配给输出变量,或者考虑改用标量函数。


因为我的代码中有多个地方单独调用了sp_LoginUser存储过程。而且在某些情况下,它是在另一个存储过程中被调用的(在这种情况下,我没有使用输出参数)。 - Manish Sapkal

0

像这样返回多个值

CREATE PROCEDURE `sp_ReturnValue`(
    p_Id int(11),                -- Input param
    OUT r_status1 INT(11)               -- output param
    OUT r_status2 VARCHAR(11)               -- output param
    OUT r_status3 INT(11)               -- output param
)
BEGIN 
    SELECT Status FROM tblUsers WHERE tblUsers_ID = p_Id; // use of input param
      SET r_status1 = 2; // use of output param
      SET r_status2 = "ABCD"; // use of string output param
      SET r_status3 = 2; // use of output param
END

并且读取为

CREATE PROCEDURE `sp_ReadReturnValue`()
BEGIN
    SELECT @ret_value1 AS ret_value1,
           @ret_value2 AS ret_value2,
           @ret_value3 AS ret_value3;
END

节点中的参数用于输出参数

con.query("CALL sp_ReturnValue(?, @ret_value1, @ret_value2, @ret_value3); CALL sp_ReadReturnValue;", [id], (err, rows) => {
                console.log("Print return value \n "); 
                console.log(rows[1][0].ret_value1 "\n");  
                console.log(rows[1][0].ret_value2 "\n");
                console.log(rows[1][0].ret_value3 );
        })

欢迎来到SO!当您发布带代码的答案时,请尽量进行一些解释。在这种情况下,由于有其他回复,因此请展示您的优点。 - David García Bodego

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接