2013-12-17 18 views
7

Ho creato alcune stored procedure nel mio database (MySQL) come segue.Procedura memorizzata MySQL che restituisce più record set

Stored Procedure 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 

stored procedure 2

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

     SELECT '3' As Result; 
    END IF 
END 

Ora io chiamo la mia prima stored procedure come segue:

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

Qui sto ottenendo 4 set di risultati in MySQL Workbench. 2 risultati da sp_Name2, 3 ° per l'istruzione di aggiornamento in sp_Name1 e 4 dall'istruzione select, anche in sp_Name1. Qui sto cercando solo l'ultimo set di risultati. A volte la sequenza dei risultati appare nell'ordine atteso, il che significa che i risultati possono entrare come risultato 1, risultato 2, risultato 4, risultato 3 (in questo caso non posso giudicare quale serie di risultati è utile per me, perché l'ultimo set di risultati può essere cambiato).

Come si eliminano i set di risultati indesiderati?

MODIFICA: Ho un caso d'uso per una migliore comprensione.

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 

Così, ora, quando il mio utente che richiede di login e di entrare nel suo/la sua nome utente con la password sulla mia pagina di login, allora ho chiamare sp_LoginUser() sul mio server. In molti casi devo chiamare sp_Login() separatamente.

Nel caso precedente posso impostare un parametro (ad esempio loginID) AS INOUT nella procedura sp_Login(), assegnare LAST_INSERT_ID() ad esso, rimuovere l'istruzione SELECT e recuperare in sp_LoginUser(). Ma quando ho bisogno di chiamare sp_Login() separatamente, devo dichiarare alcune variabili nella mia codifica per recuperare il valore.

+1

Potete per favore pubblicare un codice di esempio significativo che potremmo eseguire per riprodurre il problema che state affrontando? Il codice che hai pubblicato è completamente ambiguo. – Rachcha

risposta

7

Se non si desidera utilizzare questi set di risultati, non selezionarli.

1

Non sono sicuro del motivo per cui si seleziona LAST_INSERT_ID() in sp_Login e nuovamente in sp_LoginUser?

Se è necessario restituire LAST_INSERT_ID() da sp_Login, è necessario assegnare una variabile di output o considerare invece una funzione scalare.

+0

perché la stored procedure sp_LoginUser viene chiamata da sola da vari punti del mio codice. e in alcuni punti viene chiamato all'interno di un'altra stored procedure come menzionato sopra (dove non sto usando il parametro di output) –

2

Quando si esegue una selezione all'interno di una stored procedure, il gruppo di risultati viene restituito al client. 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

Perché i processi memorizzati? Puoi farlo con SQL normale:

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; 

Se il nome utente/password è corretta, il vostro set di righe avrà la fila per l'accesso - si potrebbe aderire alla tabella degli utenti per ottenere anche tutti i dati degli utenti anche.

Se il nome utente/password non erano corretti, avrete un set di righe vuoto.

FYI, LAST_INSERT_ID() restituisce 0 se non ci sono inserimenti precedenti.


stored procedure sono il almeno modo preferito di attuare SQL, soprattutto perché sono meno portatile vie (ci sono other good reasons troppo); se è possibile implementare in SQL semplice è un'opzione migliore. Sebbene questo SQL non sia completamente portatile, può essere facilmente convertito in quanto la maggior parte dei database ha funzioni e caratteristiche simili a mysql.

Problemi correlati