2013-12-17 3 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 Workbench. 2 результатов из sp_Name2, 3rd для оператора update в sp_Name1 и 4th из оператора select, также в sp_Name1. Здесь я ищу только последний набор результатов. Иногда последовательность результатов появляется в ожидаемом порядке, что означает, что результаты могут появляться как Результат 1, Результат 2, Результат 4, Результат 3 (В этом случае я не могу судить, какой набор результатов полезен для меня, поскольку последний набор результатов может быть изменен).

Как подавить нежелательные наборы результатов?

EDIT: У меня есть кейс для вашего лучшего понимания.

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) AS INOUT в процедуре sp_Login(), назначить ему LAST_INSERT_ID(), удалить инструкцию SELECT и получить в sp_LoginUser(). Но когда мне нужно вызвать sp_Login() отдельно, мне нужно объявить некоторую переменную в моей кодировке, чтобы получить значение.

+1

Не могли бы вы разместить какой-нибудь осмысленный образец кода, который мы могли бы запустить, чтобы воспроизвести проблему, с которой вы столкнулись? Код, который вы опубликовали, является полностью двусмысленным. – Rachcha

ответ

7

Если вы не хотите эти результирующие наборы, не выбирайте их.

1

Я не уверен, почему вы выбираете LAST_INSERT_ID() в sp_Login и снова в sp_LoginUser?

Если вам нужно вернуть LAST_INSERT_ID() из sp_Login, вам нужно либо присвоить ему выходную переменную, либо вместо этого использовать скалярную функцию.

+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

Используйте DO SELECT.., если вы не хотите, чтобы вернуть результирующий набор для выбора (http://dev.mysql.com/doc/refman/5.6/en/do.html). Тем не менее, я не понимаю, почему вы запускаете выбор в первую очередь, если вы не хотите результатов.

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.

Смежные вопросы