Возникли проблемы при выполнении нескольких курсоров в хранимой процедуре MySQL - PullRequest
0 голосов
/ 24 февраля 2011

Я пишу процедуру хранения, чтобы создать две временные таблицы и сделать выбор из двух. При использовании первого или второго курсора наедине с другими комментируемыми, процедура работает, но когда я запускаю запрос для создания процедуры с двумя курсорами, он не работает. Я изменил код, чтобы отразить предложение Айка Уокера.

Вот скрипт:

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;

выдает это как ошибку

Запрос: СОЗДАНИЕ ПРОЦЕДУРЫ joinemailsmsdailygraph (В предыдущий день VARCHAR (20), В сегодняшний день VARCHAR (20)) СЧИТЫВАЕТ, ЧТО ДАННЫЕ НАЧИНАЮТСЯ, ЧТОБЫ ЗАЯВИТЬ ЧАСЫ INT ...
Код ошибки: 1338
Объявление курсора после объявления обработчика
Время выполнения: 00: 00: 00: 000
Время трансфера: 00: 00: 00: 000
Общее время: 00: 00: 00: 000

Я попытался поместить оба обработчика продолжения в конец всего раздела объявления, но он жалуется на перекрытие блоков объявления или около того.

Подскажите, пожалуйста, что я делаю не так? Спасибо за чтение.

Ответы [ 2 ]

1 голос
/ 24 февраля 2011

Почему вы используете курсоры? Вы можете легко сделать это без таблицы 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;
1 голос
/ 24 февраля 2011

Вам нужно объявить все курсоры заранее, прежде чем начнется логика вашей процедуры.

Если вы делаете вещи в таком порядке, это должно работать:

DECLARE variables
DECLARE cursors
DECLARE handlers
...
logic
...