Having issues with MySQL Stored Procedure with multiple statements - mysql

I am having a very bad time with a MySQL stored procedure, I can't created this procedure in the database (MySQL 5.5.27)
I a wondering why its rejecting my from variable declaration, multiple select and if else (Hopefully is some code error) I am pasting my code in!
DELIMITER $$
DROP PROCEDURE IF EXISTS EditEnterprise
$$
CREATE PROCEDURE EditEnterprise(
IN pEnterpriseId VARCHAR(32),
IN pEnterpriseName VARCHAR(64)
)
/* declare the new variables */
DECLARE nEnterpriseId VARCHAR(32);
DECLARE nEnterpriseName VARCHAR(64);
/* declare the old variables */
DECLARE oEnterpriseId VARCHAR(32);
DECLARE oEnterpriseName VARCHAR(64);
BEGIN
SET autocommit = 0;
/* get the old variables */
SELECT
Enterprise_ID = oEnterpriseId,
Enterprise_Name = oEnterpriseName
FROM
enterprise
WHERE
Enterprise_ID = pEnterpriseId;
/* set the variables with the new inputs */
IF pEnterpriseName = NULL
SET nEnterpriseName = oEnterpriseName
ELSE IF pEnterpriseName = ''
SET oEnterpriseName = NULL
ELSE
SET nEnterpriseName = pEnterpriseName
UPDATE enterprise
SET
Enterprise_Name = nEnterpriseName
WHERE Enterprise_ID = pEnterpriseId;
COMMIT;
END $$
DELIMITER ;

There are some mistakes in the SP and it should be something like this
DELIMITER $$
DROP PROCEDURE IF EXISTS EditEnterprise
$$
CREATE PROCEDURE EditEnterprise(
IN pEnterpriseId VARCHAR(32),
IN pEnterpriseName VARCHAR(64)
)
BEGIN
/* declare the new variables */
DECLARE nEnterpriseId VARCHAR(32);
DECLARE nEnterpriseName VARCHAR(64);
/* declare the old variables */
DECLARE oEnterpriseId VARCHAR(32);
DECLARE oEnterpriseName VARCHAR(64);
SET autocommit = 0;
/* get the old variables */
SELECT
#oEnterpriseID := Enterprise_ID,
#oEnterpriseName := Enterprise_Name
FROM
enterprise
WHERE
Enterprise_ID = pEnterpriseId;
/* set the variables with the new inputs */
IF pEnterpriseName = NULL THEN
SET #nEnterpriseName = #oEnterpriseName;
ELSEIF pEnterpriseName = '' THEN
SET #oEnterpriseName = NULL;
ELSE
SET #nEnterpriseName = pEnterpriseName;
END IF;
UPDATE enterprise
SET
Enterprise_Name = nEnterpriseName,
Enterprise_Established_Date = nEnterpriseCreateDate,
Enterprise_Description = nEnterpriseDetails,
Enterprise_Type = nEnterpriseType,
Enterprise_Status = nEnterpriseStatus
WHERE Enterprise_ID = pEnterpriseId;
COMMIT;
END $$
DELIMITER ;
Some errors to point out
Its ELSEIF instead if ELSE IF for multiple conditions
After declaring a variable "DECLARE myvar VARCHAR(32)", we need to use := to assign values to it if we are not using the SET command.

In Mysql (which differs from Oracle), DECLARE goes after BEGIN
Your code should be:
DELIMITER $$
DROP PROCEDURE IF EXISTS EditEnterprise$$
CREATE PROCEDURE EditEnterprise(
IN pEnterpriseId VARCHAR(32),
IN pEnterpriseName VARCHAR(64)
)
BEGIN
/* declare the new variables */
DECLARE nEnterpriseId VARCHAR(32);
DECLARE nEnterpriseName VARCHAR(64);
/* declare the old variables */
DECLARE oEnterpriseId VARCHAR(32);
DECLARE oEnterpriseName VARCHAR(64);
SET autocommit = 0;
/* get the old variables */
SELECT
Enterprise_ID := oEnterpriseId,
Enterprise_Name := oEnterpriseName
FROM
enterprise
WHERE
Enterprise_ID = pEnterpriseId;
/* set the variables with the new inputs */
IF pEnterpriseName IS NULL THEN
SET nEnterpriseName = oEnterpriseName;
ELSEIF pEnterpriseName = '' THEN
SET oEnterpriseName = NULL;
ELSE
SET nEnterpriseName = pEnterpriseName;
END IF;
UPDATE enterprise SET
Enterprise_Name = nEnterpriseName
WHERE Enterprise_ID = pEnterpriseId;
COMMIT;
END$$
DELIMITER ;
I also added the missing ;, THEN and END IF keywords.
Also, take note that you might have a typo at this line:
SET oEnterpriseName = NULL;
You probably meant:
SET nEnterpriseName = NULL;
Now I think you should reconsider your stored procedure. Indeed, all this could be done in a single SQL query. Do you really need a stored procedure for this? Except if you have a restrictive grants policy it might just be superfluous.

Related

mySQL procedure does not commit on commit statement

This is my code:
BEGIN
DECLARE _cnt INT;
DECLARE i INT DEFAULT 0 ;
DECLARE j INT DEFAULT 0 ;
DECLARE _FIPSAPNCombo VARCHAR(30) DEFAULT '00000';
DECLARE _prv_FIPSAPNCombo VARCHAR(30) DEFAULT '00000';
DECLARE _Rollyear INT DEFAULT 2000;
DECLARE _first_Rollyear INT DEFAULT 2000;
DECLARE eof boolean default FALSE;
DECLARE _AvTotal INT;
DECLARE _prv_AvTotal INT default 0;
DECLARE _YOY_PCT INT;
DECLARE _YOY_USD INT;
DECLARE _in_pct INT;
DECLARE _in_usd INT;
DECLARE _last INT;
DECLARE _id INT;
DECLARE _idx INT;
DECLARE _prv_id INT;
DECLARE get_FIPSAPNCombo CURSOR
FOR
SELECT 0, '0', 2000, 1
UNION
SELECT id, FIPSAPNCombo, rollyear, AvTotal
FROM AvHistory_06037 AS h
WHERE substr(h.FIPSAPNCombo,1,8) = _in_FIPSAPNCombo_8
AND h.AvTotal > 0
ORDER BY 2, 3
;
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET eof = TRUE;
SELECT YOY_PCT, YOY_USD INTO _in_pct, _in_usd FROM AlertSearches WHERE id = _in_AlertSearchesID;
START TRANSACTION;
OPEN get_FIPSAPNCombo;
doit: LOOP
fetch get_FIPSAPNCombo INTO _id, _FIPSAPNCombo, _Rollyear, _AvTotal;
SET _YOY_USD = _AvTotal - _prv_AvTotal;
SET _YOY_PCT = ROUND((((_AvTotal - _prv_AvTotal) / _prv_AvTotal) * 100),0);
IF eof = TRUE THEN
LEAVE doit;
END IF;
IF _FIPSAPNCombo != _prv_FIPSAPNCombo THEN SET _first_Rollyear = _Rollyear; ELSE SET _first_Rollyear = '2000'; END IF;
IF _YOY_PCT >= _in_pct AND _YOY_USD >= _in_usd and _Rollyear != _first_Rollyear THEN
BEGIN
DELETE FROM AvHistoryAlerts WHERE FIPSAPNCombo = _FIPSAPNCombo AND AlertSearchesID = _in_AlertSearchesID;
INSERT INTO AvHistoryAlerts VALUES (_id, _FIPSAPNCombo, '06037', _Rollyear, _AvTotal, _YOY_PCT, _YOY_USD, _prv_id, _prv_AvTotal, _in_AlertSearchesID);
UPDATE AvHistory SET CausalTransfer = NULL WHERE FIPSAPNCombo = _FIPSAPNCombo;
UPDATE AvHistory SET CausalTransfer = 'Green' WHERE id = _id;
SET i = i + 1;
IF mod(i,1000) = 0 THEN insert into error_log VALUES (concat(_in_FIPSAPNCombo_8, ' > calc_YOY_increase i = ', i, ' ',now())); COMMIT; START TRANSACTION; END IF;
END;
END IF;
SET _prv_FIPSAPNCombo = _FIPSAPNCombo;
SET _prv_AvTotal = _AvTotal;
SET _prv_id = _id;
SET eof = FALSE;
END LOOP;
COMMIT;
CLOSE get_FIPSAPNCombo;
END
I thought that the procedure would commit every 1000 records processed and that this would be reflected in the error_log table in real time.
But, the data is only available after the procedure finishes completely and then all the records show up all at once in the error_log table.
That, by itself, is not the issue: what I am concerned about is the the procedure seems to dwell on "waiting for handler commit" for a long time at the end of the procedure.
So, I'm not sure what's going on: is it storing everything in memory or in a temp table or file and then needs a lot if time for cleanup?
I thought that a commit would clear all that... but it does not seem to commit until the end of the whole procedure
Any ideas?

mysql procedure : syntax, syntax, syntax ...... too hard to find

Here is my procedure :
delimiter //
drop procedure if exists migContactToActor;
create procedure migContactToActor()
begin
declare vctaid int;
declare firstname char(255);
declare lastname char(255);
declare phone char(255);
declare cellphone char(255);
declare fax char(255);
declare mail char(255);
declare location char(255);
declare extcode char(255);
declare vcpyid int;
declare vquaid int;
declare userModif char(255);
declare entityIdResp int;
declare niveauCreat char(255) default "contactMigration2.21";
declare userCreat char(255) default "contactMigration2.21";
declare backIdResp int;
declare userIdResp int;
declare zipcode char(255);
declare country char(255);
declare dateModif char(255);
declare dateCreated char(255);
declare dateRelation char(255);
declare groupLabel char(255);
declare adminLogId int;
declare finContact boolean default 0;
declare ctt int default 1; /* decompte contacts */
declare entityName char(255) default ''; /* entite courante du user a linker */
declare entityId int default 0; /* et son Id */
declare vctaidPrev int default 0;
declare curs1 cursor for select
ctaid, ctafirstname,ctalastname,ctaphone,ctacellphone,ctaemail,
substr(concat_ws(' ',ctaaddress,ctaaddress2,ctacity,ctazipcode),1,255),ctacode, cpyid,quaid,C.enoid_resp,
ctafax,C.actid_bck,ctadate_created,ctacountry,ctadate_modified,C.actid_resp,ctauser_modified, G.hemlabel, R.sync_update
from contact C
left join hd_contact_group_relationship R on R.hbhid = C.ctaid
left join hd_contact_group G on G.hemid = R.hemid
where !ifnull(C.ctaflagdeleted,0) and !ifnull(G.hemflag_deleted,0);
declare continue handler for not found set finContact = 1;
declare continue handler for sqlexception
begin
rollback;
end;
select '======== debut ...';
drop table if exists ent221;
create temporary table ent221 as select enoid, enoname from entityowner where enoname like 'CLI.CG_%.CLI';
alter table ent221 add index(enoname); /* not unique in dev, fetch the first in prod if any */
set autocommit = 0; /* TTT */
start transaction; /* TTT */
open curs1;
contactloop:loop
fetch curs1 into vctaid, firstname,lastname,phone,cellphone,mail,location,extcode,vcpyid,vquaid,entityIdResp,
fax,backIdResp,dateCreated,country,dateModif,userIdResp,userModif,groupLabel,dateRelation;
if finContact then
close curs1;
leave contactloop;
end if;
if vctaid = vctaidPrev then
set vctaidPrev = vctaid;
if (mod(ctt,100) = 0) then
set #msg = concat(ctt, ' contacts migrated');
select #msg;
end if;
update OPMSequence set counter = (#wbuf1 := counter) + 1 where name = 'ACTOR';
insert into actor (actid,cpyid,actlastname,actfirstname,actemail,actphone,actmobilephone,
actlocalisation, actid_responsible_owner,actid_backup_owner,enoid_responsible_owner,
actuser_created,actniveau_created, actdate_created,actuser_modified,
actdate_modified,actcountry,actfax,actqualifid,actexternal_code)
values
(#wbuf1,vcpyid,lastname,firstname,mail,phone,cellphone,location,userIdResp,backIdResp,entityIdResp,
userCreat,niveauCreat,dateCreated,userModif,dateModif,country,fax,vquaid,extcode);
update adminLog set adltype = 'User', adlobject_id = #wbuf1,
adlobject_description = concat(adlobject_description,'//oldContact=',vctaid)
where adlobject_id = vctaid and adltype = 'Contact';
end if;
if groupLabel is not null then
set #entName = concat('CLI.CG_',groupLabel,'.CLI);
select enoid from ent221 where enoname = #entName limit 1 into #wbuf2;
if #wbuf2 is not null then
insert into actorentityrelationship (enoid,actid,aerdate_created,aerniveau_created) values
(#buf2,#wbuf1,dateRelation,niveauCreat);
enf if;
end if;
set ctt = ctt + 1;
end loop contactloop;
rollback; /* TTT */
end //
delimiter ;
call migContactToActor;
drop procedure migContactToActor;
Why this ???
Query OK, 0 rows affected, 1 warning (0.00 sec)
ERROR 1064 (42000): 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 ''.CLI);
select enoid from ent221 where enoname = #entName limit 1 into #wbuf2' at line 83
I think you missed the quotes
set #entName = concat('CLI.CG_',groupLabel,'.CLI);
with quotes
set #entName = concat('CLI.CG_',groupLabel,'.CLI');

Mysql - How to split text variable in stored procedure

I have a MySQL variable as below.
DECLARE str TEXT DEFAULT '2014-01-02 13:00:00|2014-02-04 12:59:59#0#2014-02-04 13:00:00|2014-03-04 12:59:59#0#2014-03-04 13:00:00|2014-04-02 13:59:59#0#2014-04-02 14:00:00|2014-05-02 14:59:59#0#2014-05-02 15:00:00|2014-06-03 14:59:59';
I want to break this whole string first by using the separator #0# and from the results break the string using separator |.
I have tried MySQL split_str function but I am not able to do it.
Its giving me the error split_str does not exist.
Please suggest some other way to do this.
Finally i have resolved my problem using below procedure.
I am able to solve it using temporary table and procedure. I am no more using mysql variable for this. We can call the procedure as below....
CALL SplitString('2014-01-02 13:00:00|2014-02-04 12:59:59#0#2014-02-04 13:00:00|2014-03-04 12:59:59#0#2014-03-04 13:00:00|2014-04-02 13:59:59#0#2014-04-02 14:00:00|2014-05-02 14:59:59#0#2014-05-02 15:00:00|2014-06-03 14:59:59', '#0#', 'tblindex');
Here tblindex is temporary table i have used.
My procedure is below....
DELIMITER $$
DROP PROCEDURE IF EXISTS `SplitString`$$
CREATE PROCEDURE `SplitString`( IN input TEXT,IN delm VARCHAR(10),tblnm varchar(50))
BEGIN
DECLARE cur_position INT DEFAULT 1 ;
DECLARE remainder TEXT;
DECLARE cur_string VARCHAR(1000);
DECLARE delm_length TINYINT UNSIGNED;
set #sql_drop = concat("DROP TABLE IF EXISTS ",tblnm);
prepare st_drop from #sql_drop;
execute st_drop;
set #sql_create = concat("CREATE TEMPORARY TABLE ",tblnm," (value VARCHAR(2000) NOT NULL ) ENGINE=MEMORY;");
prepare st_create from #sql_create;
execute st_create;
SET remainder = input;
SET delm_length = CHAR_LENGTH(delm);
WHILE CHAR_LENGTH(remainder) > 0 AND cur_position > 0
DO
SET cur_position = INSTR(remainder, delm);
IF cur_position = 0 THEN
SET cur_string = remainder;
ELSE
SET cur_string = LEFT(remainder, cur_position - 1);
END IF;
-- select cur_string;
IF TRIM(cur_string) != '' THEN
set #sql_insert = concat("INSERT INTO ",tblnm," VALUES ('",cur_string,"');");
prepare st_insert from #sql_insert;
execute st_insert;
END IF;
SET remainder = SUBSTRING(remainder, cur_position + delm_length);
END WHILE;
END$$
DELIMITER ;

Declare variable syntax invalid in MySQL Workbench?

I am trying to create and set a variable:
DECLARE myId INT;
SET myId = 5;
However, I am getting invalid syntax complaint in MySQL Workbench:
SQL syntax error near 'DECLARE myId INT;'
I have tried the following variants:
DECLARE myId INT(4);
SET myId = 5;
DECLARE #myId INT;
SET #myId = 5;
DECLARE #myId INT(4);
SET #myId = 5;
What is wrong?
Try
SET #myId := 100;
Then if you do
select #myId;
You will get
100
As in the comment says Declare is only valid into stored programs like procedures, functions.
here you have an example of a store procedure and its call.
DELIMITER $$
CREATE PROCEDURE sp1 (x VARCHAR(5))
BEGIN
DECLARE xname VARCHAR(5) DEFAULT 'bob';
DECLARE myId INT;
SET myId = 5;
SELECT CONCAT(xname,' -- ',myId);
END;
$$
DELIMITER ;
call sp1('MY NAME');
I experienced the same problem. The variables must be declared at the beginning of the script.
DELIMITER &&
DROP PROCEDURE IF EXISTS PS_HANDLERS;
CREATE PROCEDURE PS_HANDLERS(IN ID_USER INT, OUT isError INT)
BEGIN
DECLARE USER_EMAIL VARCHAR(50);
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SET IsError = 1;
END;
SET USER_EMAIL = CONCAT(RAND(),'#',RAND(),'.com');
SET isError = 0;
INSERT INTO tbl_user VALUES(ID_USER, 'ipsum','lorem','ipsum#lorem.com','password','ROLE_USER');
SELECT
u.*
FROM
tbl_user u;
END &&
DELIMITER ;

Return INT Stored procedure

I receive error 1318 when I call this procedure in MYSQL. What am I doing wrong with this stored procedure? Am I even allowed to do something like this?
CREATE DEFINER=`root`#`localhost` PROCEDURE `CN_renumber`
(
OUT #maxCn,
OUT param1 INT,
OUT update_count INT
)
BEGIN
DECLARE sql_error TINYINT DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET sql_error = TRUE;
START TRANSACTION;
/*Renumber Cn in DBO*/
/* Set max cn and incremented afterwords */
SET #maxCn = '23206';
UPDATE dbo.billadr SET Cn = (#maxCn:=#maxCn + 1);
IF sql_error = FALSE THEN SET update_count = 1;
COMMIT;
ELSE
SET update_count = 0;
ROLLBACK;
END IF;
END
There was a problem with parameters. Try this procedure, it will fix error 1318 -
CREATE DEFINER='root'#'localhost' PROCEDURE CN_renumber
(OUT maxCn int, OUT param1 int, OUT update_count int)
BEGIN
SET #maxCn = 23206;
UPDATE billadr SET Cn = (#maxCn := #maxCn + 1);
SET maxCn = #maxCn;
END
Usage example -
SET #maxCn = NULL;
SET #param1 = NULL;
SET #update_count = NULL;
CALL CN_renumber(#maxCn, #param1, #update_count);
SELECT #maxCn, #param1, #update_count;