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

问题描述:

我在我的数据库(MySQL)中创建了一些存储过程,如下所示。返回多个记录集的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, ...); 

在这里我得到4个的结果集MySQL工作台。 2的结果来自sp_Name2,第3个用于sp_Name1中的更新语句,第4个来自select语句,同样位于sp_Name1中。在这里,我正在寻找最后的结果集。有时结果序列以预期的顺序出现,这意味着结果可能会像结果1,结果2,结果4,结果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()。

在上面的例子中,我可以在sp_Login()过程中设置一个参数(例如loginid)AS INOUT,为其分配LAST_INSERT_ID(),删除SELECT语句并在sp_LoginUser()中检索。 但是当我需要分别调用sp_Login()时,我必须在我的编码中声明一些变量来检索值。

+1

您能否请您发布一些我们可以运行的有意义的示例代码,以便重现您所面临的问题?您发布的代码完全不明确。 – Rachcha

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

我不确定为什么要在sp_Login中选择LAST_INSERT_ID(),并在sp_LoginUser中再次选择?

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

+0

,因为从我的代码中的各个地方单独调用sp_LoginUser存储过程。和一些地方它被称为在另一个存储过程中如上所述(我没有使用输出参数) –

当您在存储过程中执行选择时,结果集将返回给客户端。 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 

使用DO SELECT..如果你不想返回一个选择(http://dev.mysql.com/doc/refman/5.6/en/do.html)的结果集。但是,我不明白为什么你如果不想要结果,首先运行这些选择。

为什么存储过程?你可以用普通的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的至少优选方式,特别是因为它们是至少便携式方式(有other good reasons太);如果你能用普通的SQL实现,这是一个更好的选择。虽然这个SQL不是完全可移植的,但它可以很容易地进行转换,因为大多数数据库都具有与mysql相似的功能和特性。