mySql中使用游标的存储过程
我在 mysql 中使用游标编写了一个存储过程,但该过程需要 10 秒才能获取结果,而该结果集只有 450 条记录,因此,我想知道为什么该过程需要花费那么多时间来获取该记录。
程序如下:
DELIMITER //
DROP PROCEDURE IF EXISTS curdemo123//
CREATE PROCEDURE curdemo123(IN Branchcode int,IN vYear int,IN vMonth int)
BEGIN
DECLARE EndOfData,tempamount INT DEFAULT 0;
DECLARE tempagent_code,tempplantype,tempsaledate CHAR(12);
DECLARE tempspot_rate DOUBLE;
DECLARE var1,totalrow INT DEFAULT 1;
DECLARE cur1 CURSOR FOR
select SQL_CALC_FOUND_ROWS ad.agentCode
, ad.planType
, ad.amount
, ad.date
from adplan_detailstbl ad
where ad.branchCode=Branchcode
and ( ad.date between '2009-12-1'
and '2009-12-31')
order by ad.NUM_ID asc;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET EndOfData = 1;
DROP TEMPORARY TABLE IF EXISTS temptable;
CREATE TEMPORARY TABLE temptable (
agent_code varchar(15)
, plan_type char(12)
, sale double
, spot_rate double default '0.0', dATE DATE
);
OPEN cur1;
SET totalrow=FOUND_ROWS();
while var1 <= totalrow DO
fetch cur1 into tempagent_code
,tempplantype
,tempamount
,tempsaledate;
IF( ( tempplantype='Unit Plan'
OR tempplantype='MIP'
) OR tempplantype='STUP') THEN
select spotRate into tempspot_rate
from spot_amount
where (( monthCode=vMonth
and year=vYear)
and ( ( agentCode=tempagent_code
and branchCode=Branchcode)
and (planType=tempplantype)
));
INSERT INTO temptable VALUES(
tempagent_code
,tempplantype
,tempamount
,tempspot_rate
,tempsaledate)
;
else
INSERT INTO temptable(
agent_code
,plan_type
,sale,dATE)
VALUES( tempagent_code,tempplantype,tempamount,tempsaledate);
END IF;
SET var1=var1+1;
END WHILE;
CLOSE cur1;
select * from temptable;
DROP TABLE temptable;
END //
DELIMITER ;
I wrote a stored procedure using cursor in mysql but that procedure is taking 10 second to fetch the result while that result set have only 450 records so, I want to know that why that proedure is taking that much time to fetch tha record.
procedure as below:
DELIMITER //
DROP PROCEDURE IF EXISTS curdemo123//
CREATE PROCEDURE curdemo123(IN Branchcode int,IN vYear int,IN vMonth int)
BEGIN
DECLARE EndOfData,tempamount INT DEFAULT 0;
DECLARE tempagent_code,tempplantype,tempsaledate CHAR(12);
DECLARE tempspot_rate DOUBLE;
DECLARE var1,totalrow INT DEFAULT 1;
DECLARE cur1 CURSOR FOR
select SQL_CALC_FOUND_ROWS ad.agentCode
, ad.planType
, ad.amount
, ad.date
from adplan_detailstbl ad
where ad.branchCode=Branchcode
and ( ad.date between '2009-12-1'
and '2009-12-31')
order by ad.NUM_ID asc;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET EndOfData = 1;
DROP TEMPORARY TABLE IF EXISTS temptable;
CREATE TEMPORARY TABLE temptable (
agent_code varchar(15)
, plan_type char(12)
, sale double
, spot_rate double default '0.0', dATE DATE
);
OPEN cur1;
SET totalrow=FOUND_ROWS();
while var1 <= totalrow DO
fetch cur1 into tempagent_code
,tempplantype
,tempamount
,tempsaledate;
IF( ( tempplantype='Unit Plan'
OR tempplantype='MIP'
) OR tempplantype='STUP') THEN
select spotRate into tempspot_rate
from spot_amount
where (( monthCode=vMonth
and year=vYear)
and ( ( agentCode=tempagent_code
and branchCode=Branchcode)
and (planType=tempplantype)
));
INSERT INTO temptable VALUES(
tempagent_code
,tempplantype
,tempamount
,tempspot_rate
,tempsaledate)
;
else
INSERT INTO temptable(
agent_code
,plan_type
,sale,dATE)
VALUES( tempagent_code,tempplantype,tempamount,tempsaledate);
END IF;
SET var1=var1+1;
END WHILE;
CLOSE cur1;
select * from temptable;
DROP TABLE temptable;
END //
DELIMITER ;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
请运行以下命令并将所有结果粘贴到 http://pastie.org/
你应该更换?在执行之前在 select 语句中使用适当的测试值
please run the following and paste ALL the results into http://pastie.org/
you should replace the ?? in the select statements with proper test values before executing
游标的本质是缓慢的,您的代码中没有任何内容明显设计不良。请记住,对于您的 curosr 迭代的 450 行中的每一行,您都会发出一两个语句。每个查询都将单独运行。单独发布 450-900 份这样的声明可能会花费类似的时间。
这就是为什么您应该尽可能避免使用游标。
看起来您想要根据特定条件选择一组 ov 值或另一组值。也许您将查询拆分为两个选择查询(针对条件的每种情况)并对结果进行 UNION 操作。
It's the nature of cursors to be slow, there's nothing in your code that is obviously bad designed. Remember that for each of your 450 rows your curosr iterates over you are issuing one or two statements. Each of those queries will be run on it's own. Issuing 450-900 Statements like this on their own would probably take similar time.
That's why you should, whenever possible, try to avoid cursors.
It looks like you want to, depending on a certain criteria, select one set ov values or another. Maybe you split up your query into two select queries (for each case of the criteria) and UNION the result.