I'm not an expert with MySQL and I've problems with this Stored Procedure.
I'm trying to do the SP with conditions but I don't know what is wrong here, I have a mistake:
Error Code: 1064. You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'declare done int default 0; declare continue
handler for sqlstate '02000' set' at line 16
delimiter $$
create procedure getListPrsn(IN idEquipo INT, IN tipo char, IN Puesto INT)
begin
declare varJefe int;
declare eqpSupJefe int;
declare jefeONo cursor for select tblpuesto.PtoLiderEqp from tblequipo
inner join tblpuesto on (tblequipo.EqpID=tblpuesto.PtoEqp)
inner join tblplaza on (tblpuesto.PtoID=tblplaza.PzaPto)
inner join tblpersona on (tblplaza.PzaPrsn=tblpersona.PrsnID)
where tblequipo.EqpID=idEquipo and tblpuesto.PtoID=Puesto;
declare equipoSuperiorDeMiJefe cursor for select tblequipo.EqpEqpSup
from tblequipo
inner join tblpuesto on(tblequipo.EqpID=tblpuesto.PtoEqp)
where tblpuesto.PtoID=Puesto;
if tipo="jefe"
then
declare done int default 0;
declare continue handler for sqlstate '02000' set done=1;
open jefeONo;
begin
repeat
fetch jefeONo into varJefe;
until done end repeat;
end;
close jefeONo;
if varJefe=1
then
declare done int default 0;
declare continue handler for sqlstate '02000' set done=1;
open equipoSuperiorDeMiJefe;
begin
repeat
fetch equipoSuperiorDeMiJefe into eqpSupJefe;
until done end repeat;
end;
close equipoSuperiorDeMiJefe;
call getLider(eqpSupJefe);
else
if varJefe=0
then
call getLider(idEquipo);
end if;
end if;
end if;
end $$
delimiter ;
Problem is in the part as pointed below, where you are trying to declare a local variable inside IF .. ELSE block. You can set the variable inside if .. else block but you should declare them in the beginning
if varJefe=1
then
declare done int default 0; <-- Here
You should declare the variable at the beginning like
create procedure getListPrsn(IN idEquipo INT, IN tipo char, IN Puesto INT)
begin
declare varJefe int;
declare eqpSupJefe int;
declare done int default 0; <-- declare it here
A DECLARE has to be at the beginning of a BEGIN ... END block. You can either move them to the beginning of the procedure (the variable declaration has to be before the cursors, the handler declaration has to be after them):
delimiter $$
create procedure getListPrsn(IN idEquipo INT, IN tipo char, IN Puesto INT)
begin
declare varJefe int;
declare eqpSupJefe int;
declare done int default 0;
declare jefeONo cursor for select tblpuesto.PtoLiderEqp from tblequipo
inner join tblpuesto on (tblequipo.EqpID=tblpuesto.PtoEqp)
inner join tblplaza on (tblpuesto.PtoID=tblplaza.PzaPto)
inner join tblpersona on (tblplaza.PzaPrsn=tblpersona.PrsnID)
where tblequipo.EqpID=idEquipo and tblpuesto.PtoID=Puesto;
declare equipoSuperiorDeMiJefe cursor for select tblequipo.EqpEqpSup
from tblequipo
inner join tblpuesto on(tblequipo.EqpID=tblpuesto.PtoEqp)
where tblpuesto.PtoID=Puesto;
declare continue handler for sqlstate '02000' set done=1;
if tipo="jefe"
then
open jefeONo;
begin
repeat
fetch jefeONo into varJefe;
until done end repeat;
end;
close jefeONo;
if varJefe=1
then
open equipoSuperiorDeMiJefe;
begin
set done = 0;
repeat
fetch equipoSuperiorDeMiJefe into eqpSupJefe;
until done end repeat;
end;
close equipoSuperiorDeMiJefe;
call getLider(eqpSupJefe);
else
if varJefe=0
then
call getLider(idEquipo);
end if;
end if;
end if;
end $$
delimiter ;
or put them after the BEGIN statements before the REPEAT statements:
delimiter $$
create procedure getListPrsn(IN idEquipo INT, IN tipo char, IN Puesto INT)
begin
declare varJefe int;
declare eqpSupJefe int;
declare jefeONo cursor for select tblpuesto.PtoLiderEqp from tblequipo
inner join tblpuesto on (tblequipo.EqpID=tblpuesto.PtoEqp)
inner join tblplaza on (tblpuesto.PtoID=tblplaza.PzaPto)
inner join tblpersona on (tblplaza.PzaPrsn=tblpersona.PrsnID)
where tblequipo.EqpID=idEquipo and tblpuesto.PtoID=Puesto;
declare equipoSuperiorDeMiJefe cursor for select tblequipo.EqpEqpSup
from tblequipo
inner join tblpuesto on(tblequipo.EqpID=tblpuesto.PtoEqp)
where tblpuesto.PtoID=Puesto;
if tipo="jefe"
then
open jefeONo;
begin
declare done int default 0;
declare continue handler for sqlstate '02000' set done=1;
repeat
fetch jefeONo into varJefe;
until done end repeat;
end;
close jefeONo;
if varJefe=1
then
open equipoSuperiorDeMiJefe;
begin
declare done int default 0;
declare continue handler for sqlstate '02000' set done=1;
repeat
fetch equipoSuperiorDeMiJefe into eqpSupJefe;
until done end repeat;
end;
close equipoSuperiorDeMiJefe;
call getLider(eqpSupJefe);
else
if varJefe=0
then
call getLider(idEquipo);
end if;
end if;
end if;
end $$
delimiter ;
I fix my SP
We have to check the declaration order
1.- variables
2.- conditions
3.- cursors
4.- handlers
delimiter $$
create procedure getListPrsn(IN idEquipo INT, IN tipo CHAR, IN Puesto INT)
begin
declare varJefe int;
declare eqpSupJefe int;
declare done int default 0;
case tipo
when "jefe" then
begin
declare jefeONo cursor for select tblpuesto.PtoLiderEqp from tblequipo
inner join tblpuesto on (tblequipo.EqpID=tblpuesto.PtoEqp)
inner join tblplaza on (tblpuesto.PtoID=tblplaza.PzaPto)
inner join tblpersona on (tblplaza.PzaPrsn=tblpersona.PrsnID)
where tblequipo.EqpID=idEquipo and tblpuesto.PtoID=Puesto;
declare continue handler for sqlstate '02000' set done=1;
open jefeONo;
repeat
fetch jefeONo into varJefe;
until done end repeat;
close jefeONo;
set done=0;
if varJefe=1
then
begin
declare equipoSuperiorDeMiJefe cursor for select tblequipo.EqpEqpSup
from tblequipo
inner join tblpuesto on(tblequipo.EqpID=tblpuesto.PtoEqp)
where tblpuesto.PtoID=Puesto;
declare continue handler for sqlstate '02000' set done=1;
open equipoSuperiorDeMiJefe;
repeat
fetch equipoSuperiorDeMiJefe into eqpSupJefe;
until done end repeat;
close equipoSuperiorDeMiJefe;
call getLider(eqpSupJefe);
end;#begin del if varJefe=1
else
if varJefe=0
then
call getLider(idEquipo);
end if;
end if;
end;#begin del case JEFE
end case;
end $$
delimiter ;
Related
I have buffet table and I want to replace an ingredient with another, but my cursor replacing twice, and I get wrong answer.
Note: I'm using MySQL Workbench v 8.0.30
CREATE PROCEDURE cur_snak(in name_snak varchar(20), in old_ingred text,
in new_ingred text)
BEGIN
declare res text;
declare d int default 0;
declare c_id int ;
declare get_cur_ingred cursor for select id from buffet where `name`=name_snak;
declare continue handler for sqlstate '02000'
set d=1;
declare continue handler for sqlstate '23000'
set d=1;
open get_cur_ingred ;
lbl: loop
if d=1 then
leave lbl;
end if;
if not d=1 then
fetch get_cur_ingred into c_id ;
select insert((select ingredients from buffet where id=c_id ),
(select locate(old_ingred,ingredients) from buffet where id=c_id ),
(select length(old_ingred)),new_ingred) into res;
update buffet
set ingredients =res
where id=c_id;
end if;
end loop.
close get_cur_ingred;
END
DELIMITER $$
CREATE or replace PROCEDURE test()
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE DNO varchar(4000);
DECLARE ORG_MRK FLOAT;
DECLARE RV1 FLOAT;
DECLARE RV2 FLOAT;
DECLARE D2 FLOAT;
DECLARE D3 FLOAT;
DECLARE D FLOAT;
DECLARE D1 FLOAT;
DECLARE lst_val FLOAT;
DECLARE T FLOAT;
DECLARE CUR1 cursor for select col1,col2,col3,col4 from table1;
OPEN CUR1;
read_loop: LOOP
FETCH CUR1 INTO DNO,ORG_MRK,RV1,RV2;
WHILE CUR1%FOUND DO
BEGIN
set D1=85;
set D=100;
IF D=D1 THEN
BEGIN
UPDATE table2 SET FMARK_100=GREATEST(ORG_MRK,RV1) WHERE rtrim(ltrim(fmark_100)) =''
and RTRIM(LTRIM(DUMYNUMB))=DNO;
END;
ELSE
UPDATE table2 SET FMARK_100=lEAST(ORG_MRK,RV1) WHERE rtrim(ltrim(fmark_100)) =''
and RTRIM(LTRIM(DUMYNUMB))=DNO;
END IF;
END;
END WHILE;
END LOOP;
CLOSE CUR1;
END$$
DELIMITER ;
It created successfully,No error returns.But when call this stored procedures it gives error.
producing this error
1054 - Unknown column 'CUR1' in 'field list'.How to solve this issue. Is there any version compatibility issue.
DELIMITER $$
CREATE or replace PROCEDURE test()
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE DNO varchar(4000);
DECLARE ORG_MRK FLOAT;
DECLARE RV1 FLOAT;
DECLARE RV2 FLOAT;
DECLARE D2 FLOAT;
DECLARE D3 FLOAT;
DECLARE D FLOAT;
DECLARE D1 FLOAT;
DECLARE lst_val FLOAT;
DECLARE T FLOAT;
-- add variable-flag
DECLARE done INT DEFAULT 0;
DECLARE CUR1 cursor for select col1,col2,col3,col4 from table1;
-- add handler which sets flag when cursor is empty
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN CUR1;
read_loop: LOOP
FETCH CUR1 INTO DNO,ORG_MRK,RV1,RV2;
-- check does the record was fetched
IF done THEN
-- leave cycle if cursor is empty
LEAVE read_loop;
END IF;
set D1=85;
set D=100;
IF D=D1 THEN
UPDATE table2 SET FMARK_100=GREATEST(ORG_MRK,RV1) WHERE rtrim(ltrim(fmark_100)) =''
and RTRIM(LTRIM(DUMYNUMB))=DNO;
ELSE
UPDATE table2 SET FMARK_100=lEAST(ORG_MRK,RV1) WHERE rtrim(ltrim(fmark_100)) =''
and RTRIM(LTRIM(DUMYNUMB))=DNO;
END IF;
END LOOP;
CLOSE CUR1;
END$$
DELIMITER ;
I am reading an article on stored procedures and this is the code:
delimiter //
create procedure largest_order(out largest_id int)
begin
declare this_id int;
declare this_amount float;
declare l_amount float default 0.0;
declare l_id int;
declare done int default 0;
declare continue handler for sqlstate '02000' set done = 1;
declare c1 cursor for select orderid, amount from orders;
open c1;
repeat
fetch c1 into this_id, this_amount;
if not done then
if this_amount > l_amount then
set l_amount=this_amount;
set l_id=this_id;
end if;
end if;
until done end repeat;
close c1;
set largest_id=l_id;
end
//
delimiter ;
I am using a simple database named "mydatabase". After running the above code it gives me this error: ERROR 1338 (42000): Cursor declaration after handler declaration
What is wrong and how can I fix it?
This is my first time working with stored procedures.
Per MySql docs:
Cursor declarations must appear before handler declarations and after
variable and condition declarations.
So I updated the code as follows:
delimiter //
create procedure largest_order(out largest_id int)
begin
declare this_id int;
declare this_amount float;
declare l_amount float default 0.0;
declare l_id int;
-- 1. cursor finished/done variable comes first
declare done int default 0;
-- 2. the curser declaration and select
declare c1 cursor for select orderid, amount from orders;
-- 3. the continue handler is defined last
declare continue handler for sqlstate '02000' set done = 1;
open c1;
repeat
fetch c1 into this_id, this_amount;
if not done then
if this_amount > l_amount then
set l_amount=this_amount;
set l_id=this_id;
end if;
end if;
until done end repeat;
close c1;
set largest_id=l_id;
end
//
delimiter ;
And now works fine.
My stored procedure is like this ...
DELIMITER $$
DROP PROCEDURE IF EXISTS `tds_dev`.`BlockTokenSheduler`$$
CREATE PROCEDURE `BlockTokenSheduler`(cdate date,shift varchar(20))
BEGIN
declare lo_SERIALNO int;
declare lo_TOKENNUMBER int;
declare lo_ARRIVALTIME time;
declare lo_ADJUSTMENTTIME time;
declare lo_APPOINTMENTTIME time;
declare bt_ADJUSTMENTTIME time;
declare bt_NEXTAPPOINTMENTTIME time;
declare lo_CONSULTATIONTYPE varchar(20);
declare lo_NEXTAPPOINTMENTTIME time;
declare lo_CONSULTATIONSTATUS varchar(20);
declare lo_ACTUALFINISHEDTIME time;
declare lo_SMSSTATUS varchar(20);
declare temp_appTime time;
declare time_diff time;
declare done int;
declare btdone int;
declare btcount int;
declare co int;
Declare btcountcur Cursor for
select ADJUSTMENTTIME,NEXTAPPOINTMENTTIME from tds_tokengeneration where TOKENDATE =cdate and SHIFTID = shift and blockstatus='BT' ORDER BY APPOINTMENTTIME ;
declare continue handler for not found set btdone=1;
open btcountcur;
bt_loop :LOOP
if btdone=1 then
leave bt_loop;
end if;
FETCH btcountcur into bt_ADJUSTMENTTIME,bt_NEXTAPPOINTMENTTIME;
Declare mycur cursor for
select TOKENNUMBER,APPOINTMENTTIME,ADJUSTMENTTIME,CONSULTATIONTYPE,NEXTAPPOINTMENTTIME,CONSULTATIONSTATUS,SMSSTATUS from tds_tokengeneration
where TOKENDATE=cdate and SHIFTID=shift and blockstatus='MT';
declare continue handler for not found set done=1;
open mycur;
time_loop :LOOP
FETCH mycur into lo_TOKENNUMBER,lo_APPOINTMENTTIME,lo_ADJUSTMENTTIME,
lo_CONSULTATIONTYPE,lo_NEXTAPPOINTMENTTIME,lo_CONSULTATIONSTATUS,lo_SMSSTATUS;
if done=1 then
leave time_loop;
end if;
if (lo_ADJUSTMENTTIME >= bt_ADJUSTMENTTIME and lo_APPOINTMENTTIME <= bt_NEXTAPPOINTMENTTIME) or (lo_NEXTAPPOINTMENTTIME >= bt_ADJUSTMENTTIME and lo_NEXTAPPOINTMENTTIME <= bt_NEXTAPPOINTMENTTIME)then
set lo_ADJUSTMENTTIME=bt_NEXTAPPOINTMENTTIME;
if lo_CONSULTATIONTYPE='C' then
set lo_NEXTAPPOINTMENTTIME = ADDTIME(lo_ADJUSTMENTTIME,'00:12:00');
else
set lo_NEXTAPPOINTMENTTIME = ADDTIME(lo_ADJUSTMENTTIME,'00:20:00');
end if;
update tds_tokengeneration set ADJUSTMENTTIME=lo_ADJUSTMENTTIME,
NEXTAPPOINTMENTTIME=lo_NEXTAPPOINTMENTTIME,
SMSSTATUS=lo_SMSSTATUS
where TOKENNUMBER=lo_TOKENNUMBER and TOKENDATE=cdate and SERIALNO=lo_SERIALNO;
end if;
end loop time_loop;
close mycur;
end loop bt_loop;
close btcountcur;
END$$
DELIMITER ;
.but when i executing this program i'm getting below error
(0 row(s)affected)
(0 ms taken)
Error Code : 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Declare mycur cursor for
select TOKENNUMBER,APPOINTMENTTIME,ADJ' at line 33
(0 ms taken)
Declarations must follow a certain order.
It is not allowed to declare a cursor or an event handler in the middle of your procedure. Yes, the error message is misleading to say the least. You must declare the mycur cursor at the beginning of a BEGIN ... END block.
You could either move the second cursor declaration to the beginning of your procedure, or nest a BEGIN ... END block at an appropriate location.
can anyone help me on why the I can't create the temporary table on the stored procedure.
Here is my stored procedure script
DELIMITER $$
DROP PROCEDURE IF EXISTS getProductionItem$$
CREATE DEFINER=pvtuser#`%` PROCEDURE getProductionItem(projectID BIGINT(20))
BEGIN
CREATE TEMPORARY TABLE tempProdItem(
prodType SET('JOB','BATCH','DOCGROUP'),
taskQueueId BIGINT(20),
jobBatchDocId BIGINT(20),
jobBatchDocName VARCHAR(255),
lockStatus SET('LOCKED','OPEN')
);
DECLARE done INT DEFAULT 0;
DECLARE prodType VARCHAR(10);
DECLARE taskQueueId BIGINT(20);
DECLARE jobBatchDocId BIGINT(20);
DECLARE jobBatchDocName VARCHAR(255);
DECLARE lockStatus VARCHAR(10);
DECLARE docCursor CURSOR
FOR SELECT 'DOCGROUP',
jq.taskqueueid,
jq.documentgroupid,
dgd.documentGroupName,
COALESCE(jql.lockStatus,'OPEN')
FROM jobdetails jd
INNER JOIN jobqueue jq
ON jd.jobid=jq.jobid
INNER JOIN documentgroupdetails dgd
ON jq.documentgroupid=dgd.documentgroupid
LEFT JOIN jobqueuelocked jql
ON jq.taskqueueid=jql.taskqueueid
GROUP BY jq.taskqueueid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN docCursor;
Loop1: LOOP
FETCH docCursor INTO prodType,taskQueueId,jobBatchDocId,jobBatchDocName,lockStatus;
IF done=1 THEN
LEAVE Loop1;
ELSE
/* TODO INSERT HERE IN TEMP TABLE */
END IF;
END LOOP;
CLOSE docCursor;
SELECT * FROM tempProdItem;
END
$$
DELIMITER;
DELIMITER $$
DROP PROCEDURE IF EXISTS getProductionItem$$
CREATE DEFINER=pvtuser#`%` PROCEDURE getProductionItem(projectID BIGINT(20))
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE prodType VARCHAR(10);
DECLARE taskQueueId BIGINT(20);
DECLARE jobBatchDocId BIGINT(20);
DECLARE jobBatchDocName VARCHAR(255);
DECLARE lockStatus VARCHAR(10);
DECLARE docCursor CURSOR
FOR SELECT 'DOCGROUP',
jq.taskqueueid,
jq.documentgroupid,
dgd.documentGroupName,
COALESCE(jql.lockStatus,'OPEN')
FROM jobdetails jd
INNER JOIN jobqueue jq
ON jd.jobid=jq.jobid
INNER JOIN documentgroupdetails dgd
ON jq.documentgroupid=dgd.documentgroupid
LEFT JOIN jobqueuelocked jql
ON jq.taskqueueid=jql.taskqueueid
GROUP BY jq.taskqueueid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
CREATE TEMPORARY TABLE tempProdItem(
prodType SET('JOB','BATCH','DOCGROUP'),
taskQueueId BIGINT(20),
jobBatchDocId BIGINT(20),
jobBatchDocName VARCHAR(255),
lockStatus SET('LOCKED','OPEN')
);
OPEN docCursor;
Loop1: LOOP
FETCH docCursor INTO prodType,taskQueueId,jobBatchDocId,jobBatchDocName,lockStatus;
IF done=1 THEN
LEAVE Loop1;
ELSE
INSERT INTO tempProdItem
(prodType,taskQueueId,jobBatchDocId,jobBatchDocName,lockStatus)
VALUES (prodType,taskQueueId,jobBatchDocId,jobBatchDocName,lockStatus);
END IF;
END LOOP;
CLOSE docCursor;
SELECT * FROM tempProdItem;
END
$$
DELIMITER;