在MySQL存储过程中无法执行多个游标

时间:2011-02-23 21:47:41

标签: mysql stored-procedures loops cursor

我正在编写一个存储过程来创建两个临时表做两个联合选择。 当单独使用第一个或第二个光标与另一个注释时,该过程有效, 但是当我运行查询以使用2个游标创建过程时,它会失败。我已经更改了代码以反映Ike Walker的建议。

这是脚本:

DELIMITER //

DROP PROCEDURE IF EXISTS joinemailsmsdailygraph//

CREATE PROCEDURE joinemailsmsdailygraph(IN previousDay VARCHAR(20), IN today VARCHAR(20))
READS SQL DATA

BEGIN

DECLARE hours INT;
DECLARE sms INT;
DECLARE email INT;
DECLARE smsdone INT DEFAULT 0;
DECLARE emaildone INT DEFAULT 0;


DECLARE cursorsms CURSOR FOR SELECT HOUR(sm.date_created) AS `HOUR OF DAY`, COUNT(*) AS smscount 
FROM sms_message_delivery smd 
JOIN sms_message sm ON sm.sms_message_id = smd.sms_message_id
WHERE DATE(sm.date_created) >= DATE(previousDay) AND DATE(sm.date_created) < DATE(today) 
GROUP BY HOUR(sm.date_created);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET smsdone =1;


DECLARE cursoremail CURSOR FOR SELECT HOUR(em.date_created) AS `HOUR OF DAY`, COUNT(*) AS emailcount 
FROM email_message_delivery emd
LEFT JOIN email_message em ON emd.email_message_id=em.email_message_id
WHERE DATE(em.date_created) >= DATE(previousDay) AND DATE(em.date_created) < DATE(today)  
GROUP BY HOUR(em.date_created);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET emaildone =1;

DROP TEMPORARY TABLE IF EXISTS tempsms;
CREATE TEMPORARY TABLE tempsms (hours_day INT, sms_count INT, email_count INT);

OPEN cursorsms;
sms_loop: LOOP

FETCH cursorsms INTO hours , sms;

IF smsdone = 1 THEN
 LEAVE sms_loop;
END IF;

INSERT INTO tempsms (hours_day, sms_count) VALUES (hours, sms);

END LOOP sms_loop;
CLOSE cursorsms;


DROP TEMPORARY TABLE IF EXISTS tempemail;

CREATE TEMPORARY TABLE tempemail (hours_day INT , sms_count INT , email_count INT);

OPEN cursoremail;
email_loop: LOOP

FETCH cursoremail INTO hours, email;

IF emaildone=1 THEN
 LEAVE email_loop;
END IF;

INSERT INTO tempemail(hours_day, email_count) VALUES(hours, email);

END LOOP email_loop;
CLOSE cursoremail;


SELECT hours_day, sms_count , email_count FROM tempsms
UNION
SELECT hours_day, sms_count, email_count FROM tempemail;

END//
DELIMITER;

它将此作为错误

  

查询:CREATE PROCEDURE joinemailsmsdailygraph(IN previousDay VARCHAR(20),IN今天VARCHAR(20))READS SQL DATA BEGIN DECLARE小时INT ...
  错误代码:1338
  处理程序声明后的游标声明
  执行时间:00:00:00:000
  转机时间:00:00:00:000
  总时间:00:00:00:000

我已尝试在所有声明部分的末尾放置两个继续处理程序,但它抱怨声明块重叠等。

你能告诉我我做错了什么吗?谢谢你的阅读。

2 个答案:

答案 0 :(得分:1)

在程序逻辑开始之前,您需要预先声明所有游标。

如果您按此顺序执行操作,则应该有效:

DECLARE variables
DECLARE cursors
DECLARE handlers
...
logic

答案 1 :(得分:1)

你为什么使用游标?只需使用联合,你就可以在没有tmp表的情况下轻松完成这项工作。

drop procedure if exists join_email_sms_daily_graph;

delimiter #

create procedure join_email_sms_daily_graph
(
in previousDay varchar(20), 
in today varchar(20)
)
begin

create temporary table tmp
(
 hours_day int unsigned, 
 sms_count int unsigned default 0, 
 email_count int unsigned default 0
)engine=memory;

insert into tmp (hours_day, sms_count) 
select
 hour(sm.date_created) as hours_day, 
 count(*) AS sms_count 
from
 sms_message_delivery smd 
join sms_message sm ON sm.sms_message_id = smd.sms_message_id
where
 date(sm.date_created) >= date(previousDay) and date(sm.date_created) <  date(today) 
group by
 hour(sm.date_created);

insert into tmp (hours_day, email_count) 
select 
 hour(em.date_created) as hours_day, 
 count(*) AS email_count 
from
 email_message_delivery emd
left join email_message em ON emd.email_message_id=em.email_message_id
where
 date(em.date_created) >= date(previousDay) and date(em.date_created) < date(today)  
group by
 hour(em.date_created);

select * from tmp; 

drop temporary table if exists tmp;

end#

delimiter;