2013-12-17 103 views
7

我在我的數據庫(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

回答

7

如果您不想要這些結果集,請不要選擇它們。

1

我不確定爲什麼要在sp_Login中選擇LAST_INSERT_ID(),並在sp_LoginUser中再次選擇?

如果您需要從sp_Login返回LAST_INSERT_ID(),則需要爲其分配輸出變量,或者考慮使用標量函數。

+0

,因爲從我的代碼中的各個地方單獨調用sp_LoginUser存儲過程。和一些地方它被稱爲在另一個存儲過程中如上所述(我沒有使用輸出參數) –

2

當您在存儲過程中執行選擇時,結果集將返回給客戶端。 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 
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的至少優選方式,特別是因爲它們是至少便攜式方式(有other good reasons太);如果你能用普通的SQL實現,這是一個更好的選擇。雖然這個SQL不是完全可移植的,但它可以很容易地進行轉換,因爲大多數數據庫都具有與mysql相似的功能和特性。

相關問題