7

是否可以將準備好的語句的結果設置爲變量?我試圖創建下面的存儲過程,但它失敗:如何從準備好的語句中獲得標量結果?

31行錯誤1064(42000):您的SQL語法錯誤;檢查與你的MySQL服務器版本相對應的手冊,在'stmt USING @m,@c,@a;

DROP PROCEDURE IF EXISTS deleteAction; 

DELIMITER $$ 
CREATE PROCEDURE deleteAction(
    IN modul CHAR(64), 
    IN controller CHAR(64), 
    IN actn CHAR(64)) 

MODIFIES SQL DATA 

BEGIN 

    PREPARE stmt FROM 'SELECT id 
         FROM actions 
         WHERE `module` = ? 
          AND `controller` = ? 
          AND `action` = ?'; 

    SET @m = modul; 
    SET @c = controller; 
    SET @a = actn; 

    SET @i = EXECUTE stmt USING @m, @c, @a; 

    DEALLOCATE PREPARE stmt; 

    DELETE FROM acl WHERE action_id = @i; 
    DELETE FROM actions WHERE id = @i; 

END 
$$ 
DELIMITER ; 

回答

6

它可能看起來很奇怪,但你可以變量直接在準備好的聲明字符串賦值:

PREPARE stmt FROM 'SELECT @i := id FROM ...'; 

-- ... 

EXECUTE stmt USING @m, @c, @a; 

-- @i will hold the id returned from your query. 

測試用例:

CREATE TABLE actions (id int, a int); 

INSERT INTO actions VALUES (1, 100); 
INSERT INTO actions VALUES (2, 200); 
INSERT INTO actions VALUES (3, 300); 
INSERT INTO actions VALUES (4, 400); 
INSERT INTO actions VALUES (5, 500); 

DELIMITER $$ 
CREATE PROCEDURE myProc(
    IN p int 
) 

MODIFIES SQL DATA 

BEGIN 

    PREPARE stmt FROM 'SELECT @i := id FROM actions WHERE `a` = ?'; 

    SET @a = p; 

    EXECUTE stmt USING @a; 

    SELECT @i AS result; 

    DEALLOCATE PREPARE stmt; 

END 
$$ 
DELIMITER ; 

結果:

CALL myProc(400); 

+---------+ 
| result | 
+---------+ 
|  4 | 
+---------+ 
1 row in set (0.00 sec) 
+0

啊!當然!! – 2010-10-21 22:37:41

+0

我知道這個答案是非常古老的,但任何人都可以告訴我:當我使用這段代碼並使用CALL myProc(600)時,它不返回空查詢結果,而是返回最後一次「有效」調用。爲什麼是這樣的,我該如何改變這一點?當我傳遞一個不在表中的值時,它應該將'result'返回爲空。 – Meelah 2017-10-18 15:11:41

1

甚至不知道你爲什麼使用動態SQL在你的榜樣 - 這似乎簡單得多

drop procedure if exists deleteAction; 

delimiter # 

create procedure deleteAction 
(
in p_modul char(64), 
in p_controller char(64), 
in p_actn char(64) 
) 
begin 

declare v_id int unsigned default 0; 

    select id into v_id from actions where 
      module = p_modul and controller = p_controller and action = p_actn; 

    delete from acl where action_id = v_id; 
    delete from actions where id = v_id; 

    select v_id as result; 

end # 

delimiter ; 

call deleteAction('mod','ctrl','actn'); 
2

使用此代碼

PREPARE stmt FROM 'SELECT ''a'' into @i' ; 

EXECUTE stmt; 

if(@i='a') then 
............ 
end if;