【问题标题】:Having trouble doing multiple cursors in a MySQL stored procedure在 MySQL 存储过程中执行多个游标时遇到问题
【发布时间】:2011-07-03 03:02:27
【问题描述】:

我正在编写一个存储过程来创建两个临时表,并对两者进行联合选择。 当单独使用第一个或第二个光标和另一个注释时,该过程有效, 但是当我运行查询以使用 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 today VARCHAR(20)) READS SQL DATA BEGIN DECLARE hours INT...
错误代码:1338
处理程序声明后的光标声明
执行时间:00:00:00:000
转机时间:00:00:00:000
总时间:00:00:00:000

我尝试将两个 continue 处理程序放在所有声明部分的末尾,但它抱怨声明块重叠左右。

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

【问题讨论】:

  • 您使用光标而不是选择进入的任何特殊原因?

标签: mysql stored-procedures loops cursor


【解决方案1】:

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

如果您按此顺序执行操作,它应该可以工作:

DECLARE variables
DECLARE cursors
DECLARE handlers
...
logic

【讨论】:

  • 嗨,Ike,您能否详细说明一下您的解释,如果可能的话,请使用小型工作示例。我将不胜感激。谢谢 ;)
【解决方案2】:

你为什么使用游标?您可以在没有 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;

【讨论】:

  • f00 非常感谢。你的解决方案很有效,只是让我意识到我想要实现的目标无法用这种方法完成。谢谢
猜你喜欢
  • 2020-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-21
  • 1970-01-01
  • 2011-02-18
相关资源
最近更新 更多