I have written following mysql stored procedure.
CREATE DEFINER=`clocery`#`%` PROCEDURE `ADMIN_ADD_NEW_USER`(IN `IN_FIRST_NAME` varchar(50),IN `IN_LAST_NAME` varchar(50),IN `IN_USER_NAME` varchar(50), IN `IN_EMAIL` varchar(50),IN `IN_PASSWORD` varchar(80),IN `IN_ROLE` varchar(20),IN `IN_CREATED_BY` INT,OUT `OUT_STATUS` char(1),OUT `OUT_MESSAGE` varchar(200))
BEGIN
DECLARE logged_in_user_role_id INT;
DECLARE to_be_created_user_role_id INT;
DECLARE user_who_created_logged_in_user INT;
DECLARE matching_row_count_user_name INT;
DECLARE matching_row_count_user_e_mail INT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
GET DIAGNOSTICS CONDITION 1 #sqlstate = RETURNED_SQLSTATE, #errno = MYSQL_ERRNO, #text = MESSAGE_TEXT;
CALL UTIL_LOG_ERROR( 'ADMIN_ADD_NEW_USER', #sqlState, #errno, #text);
SELECT 'N', UTIL_GET_ERROR_MESSAGE( 'some-error' )
INTO OUT_STATUS, OUT_MESSAGE;
END;
/**
* If passed user_id is NULL.
*/
IF IN_CREATED_BY = NULL THEN
SELECT 'N', UTIL_GET_ERROR_MESSAGE( 'some-error' )
INTO OUT_STATUS, OUT_MESSAGE;
CALL LOG_ERROR( 'ADD_NEW_USER', UTIL_GET_ERROR_MESSAGE( 'in-created-by-null' ));
ELSE
SELECT U.ROLE_ID, U.CREATED_BY INTO logged_in_user_role_id, user_who_created_logged_in_user FROM USERS U WHERE U.ID = IN_CREATED_BY;
SELECT R.ID INTO to_be_created_user_role_id FROM ROLES R WHERE R.ROLE = IN_ROLE;
/**
* If user has provided invalid role.
*/
IF to_be_created_user_role_id = NULL THEN
SELECT 'N', UTIL_GET_ERROR_MESSAGE( 'in-valid-role-provided' ) INTO OUT_STATUS, OUT_MESSAGE;
ELSE
/**
* Lets' see if logged in user has more authority than the one we are trying to create.
*/
IF to_be_created_user_role_id <= logged_in_user_role_id THEN
SELECT 'N', UTIL_GET_ERROR_MESSAGE( 'permission-denied' ) INTO OUT_STATUS, OUT_MESSAGE;
CALL CREATE_NOTIFICATION_FOR_USER( user_who_created_logged_in_user, CONCAT( GET_USER_IDENTIFICATION( IN_CREATED_BY), 'tried to create an account of higher authority.'));
ELSE
/**
* Lets' check if user name already present in the database.
*/
SELECT COUNT(*) INTO matching_row_count_user_name FROM USERS U WHERE U.USER_NAME = IN_USER_NAME;
SELECT COUNT(*) INTO matching_row_count_user_e_mail FROM USERS U WHERE U.EMAIL = IN_EMAIL;
IF matching_row_count_user_name > 0 THEN
SELECT 'N', UTIL_GET_ERROR_MESSAGE('username-exists') INTO OUT_STATUS, OUT_MESSAGE;
ELSEIF matching_row_count_user_e_mail > 0 THEN
SELECT 'N', UTIL_GET_ERROR_MESSAGE( 'email-exists' ) INTO OUT_STATUS, OUT_MESSAGE;
ELSE
/**
* Now, we are good to insert.
*/
START TRANSACTION;
/**
* Inserting into credentials first.
*/
INSERT INTO CREDENTIALS( PASSWORD, LOCKED ) VALUES ( IN_PASSWORD, 'N' );
INSERT INTO USERS( F_NAME, L_NAME, USER_NAME, EMAIL, ROLE_ID, ACTIVE, DELETED, CREATED_BY, CREATED_DATE, CREDENTIAL_ID, LAST_ACTOR_ID )
VALUES( IN_FIRST_NAME, IN_LAST_NAME, IN_USER_NAME, IN_EMAIL, to_be_created_user_role_id, 'Y', 'N', IN_CREATED_BY, NOW(), LAST_INSERT_ID(), IN_CREATED_BY );
INSERT INTO HISTORY_USER_EVENTS( USER_ID, TEXT, TYPE ) VALUES( LAST_INSERT_ID(),
CONCAT( UTIL_GET_USER_IDENTIFICATION( LAST_INSERT_ID() ), '''s account was created by ', UTIL_GET_USER_IDENTIFICATION( IN_CREATED_BY ), '.'),
UTIL_GET_EVENT_ID_FOR_ACCOUNT_ACTION( 'Created' ));
INSERT INTO HISTORY_ADMIN_EVENTS( ADMIN_ID, TEXT, TYPE ) VALUES( IN_CREATED_BY,
CONCAT( UTIL_GET_USER_IDENTIFICATION( IN_CREATED_BY ), ' created account of ', UTIL_GET_USER_IDENTIFICATION( LAST_INSERT_ID()), ' with role ', IN_ROLE, '.' ),
UTIL_GET_EVENT_ID_FOR_USER_ADDITION( IN_ROLE ));
SELECT 'Y', 'User created.' INTO OUT_STATUS, OUT_MESSAGE;
COMMIT;
END IF;
END IF;
END IF;
END IF;
END
As you can see, I have created a handler that executes in case of any SQL exception. The procedure should produce a lot of run time errors. However,
I am not able to retrieve any of the RETURNED_SQL_STATE or MYSQL_ERROR_CODE OR MESSAGE_TEXT ? They all get value null.
Is it because I am calling rollback initially ? And it somehow messes up all the relevant information ?
Here is the example of rollback code block with ability to log the error to some other table without loosing the exception details in MySQL and throwing the error again after logging it. You should get diagnostics BEFORE the ROLLBACK.
# CREATE PROCEDURE AND OTHER DECLARE STATEMENTS HERE
# ....
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 #sqlstate = RETURNED_SQLSTATE, #errno = MYSQL_ERRNO, #text = MESSAGE_TEXT;
ROLLBACK;
SET #full_error = CONCAT('ERR:', #errno, '(', #sqlstate, '):', #text);
CALL sp_logaction(#full_error); # Some logging procedure
RESIGNAL;
END;
# PROCEDURE BODY WITH START TRANSACTION & COMMIT HERE
# .....
Seems you miss to add DELIMITER in your script.
DELIMITER |
you code .. .. ..
DELIMITER;
Thanks
Related
I have a stored procedure "let's call it MY_NEW_SP" in which I'm not using BEGIN TRY / BEGIN CATCH. but, when I'm excecuting this SP (MY_NEW_SP), I get the following error:
Msg 266, Level 16, State 2, Procedure <MY_NEW_SP>, Line 132
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.
This new stored procedure makes a big select basically, no transactions are made "in the sense of make DML operations on tables (INSERT, DELETE, UPDATE)", but in temp tables "i.e. #tmp".
I'm thinking this transaction error is due I'm using SET XACT_ABORT ON; in other stored procedures, but, I'm not sure.
I follow what it is said here: C. Using TRY...CATCH with XACT_STATE
The basic structure of the stored procedure that uses SET XACT_ABORT ON; is as follows:
IF NOT EXISTS (SELECT * FROM sysobjects WHERE TYPE = 'P' AND NAME = 'PROCEP_NEW_SP' )
BEGIN
EXEC dbo.sp_executesql #statement = N'CREATE PROCEDURE PROCEP_NEW_SP AS'
END
GO
ALTER PROCEDURE PROCEP_NEW_SP
(
#ID_TABLE INT
)
AS
BEGIN
DECLARE #TBL_CONSECUTIVE TABLE ( LOG_CONSECUTIVE INT );
SET XACT_ABORT ON;
BEGIN TRANSACTION
BEGIN TRY
IF ISNULL(#ID_TABLE, -1) = -1
BEGIN
SET #ID_TABLE = 1;
DELETE FROM #TBL_CONSECUTIVE;
INSERT INTO T_BH_LOG_TABLE (ASO_NCODE, CHA_NCODE, TSO_NCODE,
MSO_DACTION_DATE, MSO_CRESULT, MSO_CCAUSE_FAILURE)
OUTPUT INSERTED.MSO_NCODE INTO #TBL_CONSECUTIVE
SELECT #ASO_NCODE, ISNULL(#CHA_NCODE, 1), ISNULL(#TSO_NCODE, 1),
GETDATE() AS MSO_DACTION_DATE, #CST_FAIL_OR_SUC, #CST_GENERIC_MSG;
IF (XACT_STATE()) = 1
BEGIN
COMMIT TRANSACTION;
END
SELECT NULL Id_table, 'Failed' Result_process, 'Parameter (ID_TABLE) is required.' Result_process_message;
RETURN;
END
-- Operation:
UPDATE MY_TABLE
SET NAME = 'SAMPLE'
WHERE ID_TABLE = #ID_TABLE;
IF (XACT_STATE()) = 1
BEGIN
COMMIT TRANSACTION;
END
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
INSERT INTO T_BH_LOG_TABLE (ASO_NCODE, CHA_NCODE, TSO_NCODE,
MSO_DACTION_DATE, MSO_CRESULT, MSO_CCAUSE_FAILURE)
OUTPUT INSERTED.MSO_NCODE INTO #TBL_CONSECUTIVE
SELECT 1 AS ASO_NCODE, 1, 1 As TSO_NCODE,
GETDATE() AS MSO_DACTION_DATE, #CST_FAIL_OR_SUC, #CST_GENERIC_MSG;
SELECT NULL Id_table, 'Failed' Result_process, 'Internal error. See log # (' + CAST(L.LOG_CONSECUTIVE AS NVARCHAR) + ') for more details.' Result_process_message;
FROM #TBL_CONSECUTIVE L;
RETURN;
END CATCH
END;
I really don't know if by using SET XACT_ABORT ON; is causing this kind of error.
Anyone can point me in the right direction for solve this issue?
imagine you have two tables.
Data are filled by an external process into one of the tables (here called "event") and they are processed by a call of a stored procedure which takes some parameters and tries to find records in table "event". If it finds it it creates a record in the second table "action" and marks the matching records in "event" to prevent them to be processed again if the procedure should run again.
Under normal circumstances I would have used a "cursor for update" on table "event" and set the field to processed in the loop of the cursor. But it seems MySQL does not support that. So I looked for an alternative way. I just store the IDs of the matching records of table "event" in a temporary table and later try to update table "event" with the constraint on the IDs stored in the temporary table.
The procedure is to be called by a shell script that sets a variable to the date of today and passes it to the procedure.
What I expect is that only the records of table "event" with the IDs from the temporary table are updated. But what happens is: all records of table "event" with the field event.submitted of today are updated.
Can anybody try to explain that? I cannot find my fallacy...
You can check the behaviour youself.
This generates the tables (change database name to match yours):
use yourdatabasename;
drop table if exists event;
create table if not exists event
(
id integer not null AUTO_INCREMENT,
sender varchar(127) not null,
name varchar(127) not null,
submitted Timestamp DEFAULT CURRENT_TIMESTAMP,
status varchar(127) not null,
logged Timestamp DEFAULT CURRENT_TIMESTAMP,
ub_status varchar(127) not null,
ub_status_date Timestamp DEFAULT CURRENT_TIMESTAMP,
primary key (id)
);
-- create some entries in "event" with decending timestamps
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name1', now(), 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name2', now() - interval 1 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name3', now() - interval 2 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name4', now() - interval 3 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name5', now() - interval 4 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name6', now() - interval 5 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name7', now() - interval 6 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name8', now() - interval 7 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name9', now() - interval 8 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
drop table if exists action;
create table if not exists action
(
id integer not null AUTO_INCREMENT,
name varchar(127) not null,
sender varchar(127) not null,
logged Timestamp not null DEFAULT CURRENT_TIMESTAMP,
status varchar(127) not null,
status_date Timestamp DEFAULT CURRENT_TIMESTAMP,
primary key (id)
);
This is the stored procedure:
CREATE DEFINER=`flo_db`#`localhost` PROCEDURE `TestUpdateActionTwoJobs`(IN process_name varchar(40),
IN sendingMachine varchar(127),
IN jobname1 varchar(127),
IN jobname2 varchar(127),
IN startdate varchar(10),
IN update_event_table int)
begin
DECLARE found_count long;
DECLARE exit handler for sqlexception
BEGIN
GET DIAGNOSTICS CONDITION 1 #sqlstate = RETURNED_SQLSTATE,
#errno = MYSQL_ERRNO, #text = MESSAGE_TEXT;
SET #full_error = CONCAT("ERROR ", #errno, " (", #sqlstate, "): ", #text);
SELECT #full_error;
ROLLBACK;
END;
DECLARE exit handler for sqlwarning
BEGIN
GET DIAGNOSTICS CONDITION 1 #sqlstate = RETURNED_SQLSTATE,
#errno = MYSQL_ERRNO, #text = MESSAGE_TEXT;
SET #full_error = CONCAT("ERROR ", #errno, " (", #sqlstate, "): ", #text);
SELECT #full_error;
ROLLBACK;
END;
/* The procedure searches for certain records in table "event" - some fields have to match, some come
* from stored procedure parameters.
* If there is a match a new record is to be created in table "action" and the found records
* in table "event" are to marked as "processed" by setting the column "event.ub_status" to "PROCESSED"
*/
SET #found_count = 0;
SET #found_tmp = 0;
START TRANSACTION;
select count(*) from event where
sender = sendingMachine
and status = 'COMPLETED_SUCCESS'
and submitted > startdate
and (name = jobname1 or name = jobname2)
and ub_status = 'CREATED' into #found_count ;
/* we expect exactly 2 */
IF #found_count = 2 THEN
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_UpdateActionTwoJobs
select id from event where
sender = sendingMachine
and status = 'COMPLETED_SUCCESS'
and submitted > startdate
and (name = jobname1 or name = jobname2)
and ub_status = 'CREATED';
INSERT INTO action (name, sender, logged, status, status_date) VALUES (process_name, sendingMachine,
NOW(), 'CREATED', NOW());
/* count the number of records in the temporary table */
select count(*) from tmp_UpdateActionTwoJobs into #found_tmp;
SET #info = CONCAT("number of records in tmp-table: ", #found_tmp);
/* mark the records as processed if wanted */
IF update_event_table = 1 THEN
UPDATE event SET ub_status = 'PROCESSED', ub_status_date = NOW() WHERE id in (select id tmp_UpdateActionTwoJobs );
END IF;
else
set #info = "no condition met!";
END IF;
COMMIT;
/* generate info output */
SELECT #info;
end
To call the procedure you could use a bash script like this (user, password, host and name of the database must be substituted...):
#!/bin/bash
# we are looking for entries in "event" that were created today
today=$(date '+%Y-%m-%d')
mysql -u database_user -p'password' -h host -e "call TestUpdateActionTwoJobs('TargetJobname', '192.168.0.2', 'name2', 'name3', '$today', 1);" database_name
Thanks a lot!
I rewrote you procedure to work with a cursor, so that there is no need for a temporary table.
Your query Works, but my security settings don't allow it because
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
But i used
select id FROM tmp_UpdateActionTwoJobs ;
instead of that what you wrote.
So try my stored procedure
USE `testdb`;
DROP procedure IF EXISTS `TestUpdateActionTwoJobs`;
DELIMITER $$
USE `testdb`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `TestUpdateActionTwoJobs`(IN process_name varchar(40),
IN sendingMachine varchar(127),
IN jobname1 varchar(127),
IN jobname2 varchar(127),
IN startdate varchar(20),
IN update_event_table int)
begin
DECLARE found_count long;
DECLARE _id long;
DECLARE finished INTEGER DEFAULT 0;
DEClARE curid
CURSOR FOR
select id from event where
sender = sendingMachine
and status = 'COMPLETED_SUCCESS'
and submitted > startdate
and (name = jobname1 or name = jobname2)
and ub_status = 'CREATED';
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
DECLARE exit handler for sqlexception
BEGIN
GET DIAGNOSTICS CONDITION 1 #sqlstate = RETURNED_SQLSTATE,
#errno = MYSQL_ERRNO, #text = MESSAGE_TEXT;
SET #full_error = CONCAT("ERROR ", #errno, " (", #sqlstate, "): ", #text);
SELECT #full_error;
ROLLBACK;
END;
DECLARE exit handler for sqlwarning
BEGIN
GET DIAGNOSTICS CONDITION 1 #sqlstate = RETURNED_SQLSTATE,
#errno = MYSQL_ERRNO, #text = MESSAGE_TEXT;
SET #full_error = CONCAT("ERROR ", #errno, " (", #sqlstate, "): ", #text);
SELECT #full_error;
ROLLBACK;
END;
/* The procedure searches for certain records in table "event" - some fields have to match, some come
* from stored procedure parameters.
* If there is a match a new record is to be created in table "action" and the found records
* in table "event" are to marked as "processed" by setting the column "event.ub_status" to "PROCESSED"
*/
SET #found_count = 0;
SET #found_tmp = 0;
START TRANSACTION;
select count(*) from event where
sender = sendingMachine
and status = 'COMPLETED_SUCCESS'
and submitted > startdate
and (name = jobname1 or name = jobname2)
and ub_status = 'CREATED' into #found_count ;
SET #found_tmp = 0;
IF #found_count = 2 THEN
INSERT INTO action (name, sender, logged, status, status_date) VALUES (process_name, sendingMachine,
NOW(), 'CREATED', NOW());
OPEN curid;
getid: LOOP
FETCH curid INTO _id;
IF finished = 1 THEN
LEAVE getid;
END IF;
UPDATE event SET ub_status = 'PROCESSED', ub_status_date = NOW() WHERE id = _id;
SET #found_tmp = #found_tmp +1;
END LOOP getid;
CLOSE curid;
SET #info = CONCAT("number of records in processed: ", #found_tmp);
ELSE
set #info = "no condition met!";
/* we expect exactly 2 */
END IF;
COMMIT;
/* generate info output */
SELECT #info;
end$$
DELIMITER ;
I am working with a bank database with two tables i.e [Card] and [Transaction].
I have created a stored procedure login that gets as inputs pin and cardNumber and returns the validity of card in an output parameter. Now, I have created another stored procedure withdraw that gets inputs pin, cardNum, transactionAmount and starts a transaction. I am trying to use p1 procedure to handle the validity part. Here are the 2 procedures
create procedure login
#status int output,
#pin varchar(4),
#cnum varchar(20)
as
begin
if exists (select * from [Card] where PIN = #pin AND cardNum = #cnum)
begin
set #status = 1
end
else
begin
set #status = 0
end
end
alter procedure WithDraw
#pin varchar(4),
#cnum varchar(20),
#trAmount int
as
begin
declare #m int
exec login #pin = N'0234', #cnum = N'2324325423336', #status = #m OUTPUT
if (select #m) = 1
--if exists (select * from [Card] where cardNum = #cnum AND pin = #pin)
--working fine with above statement
begin
if exists (select * from [Card]
where cardNum = #cnum AND pin = #pin AND (balance > #trAmount))
begin
update [Card]
set balance = balance - #trAmount
where cardNum = #cnum AND pin = #pin
declare #maxID int
select #maxID = MAX(transId) from [Transaction]
insert into [Transaction]
values (#maxID + 1, GETDATE(), #cnum, #trAmount, 1)
print 'Transaction successful'
end
else
begin
select #maxID = MAX(transId) from [Transaction]
insert into [Transaction]
values(#maxID + 1, GETDATE(), #cnum, #trAmount, 4)
print 'Transaction unsuccessful! Insufficient balance in card'
end
end
else
begin
print 'login failed'
end
end
exec WithDraw #pin = N'1770', #cnum = N'1324327436569', #trAmount = 50000
However, when I execute withdraw with login procedure inside, login always fails. When i execute without login procedure everything works fine. Any help will be greatly appreciated.
This one is a little squirrely!
I have built a stored procedure that works fine. However, when I put it into a Laravel (eloquent) migration, the migration builds the stored procedure but when it is called it gives me an error 1292 (Truncated incorrect DOUBLE value). From mysql workbench, I then right click on the stored procedure built by the migration, copy the create statement, delete the stored procedure and rebuild it from its own create statement.... AND..... EVERYTHING WORKS FINE!
I am open to any and all guesses. I obviously want this stored procedure to be part of my migrations and not have it be something that needs to be built manually. Thanks in advance:
DELIMITER $$
CREATE PROCEDURE sp_cancelTasksOnApplicationCancel(IN loanAppId INT(20))
BEGIN
SELECT loanAppId;
#SET #taskids := 0;
update tasks set task_status = 26, task_status_note = 'Application Cancelled or Denied'
where loan_app_id = loanAppId AND task_status IN (22, 23, 24) AND ( SELECT #taskids := CONCAT_WS(',', id, #taskids) );
#SELECT #taskids;
SET #cleanids = SUBSTRING(#taskids, 1, CHAR_LENGTH(#taskids) -1);
#SELECT #cleanids;
SET #pos = 0;
SET #len = 0;
WHILE LOCATE(',', #cleanids, #pos+1) > 0 DO
SET #len = LOCATE(',', #cleanids,#pos+1) - #pos;
SET #id = SUBSTRING(#cleanids, #pos, #len);
#select (#id);
IF (#id <> 0) THEN
insert into status_historys
(loan_app_id, `type`, type_recid, type_keyfield,type_status_field, type_status_date_field, type_status_note_field, type_status_userid_field, `status`, status_date, status_note, status_userid, created_at, updated_at)
values(loanAppId, 'tasks', #id, 'id', 'task status', 'tasks status datetime', 'tasks status note', 'tasks status userid', 26, now(), 'Application Cancelled or Denied', 1, now(), now());
END IF;
SET #pos = LOCATE(',', #taskids, #pos+#len) + 1;
END WHILE;
END $$
DELIMITER ;
############## UPDATE
The problem lies in the following two lines. Even from the command line it gives a warning about the incorrect double value.
SET #taskids := '0';
update tasks set task_status = 22, task_status_note = 'Just Testing'
where loan_app_id = loanAppId AND task_status IN (22, 23, 24) AND ( SELECT
#taskids := CONCAT_WS(',', cast(id as char), #taskids) );
OK - The main problem was the select keyword in the update where clause. I believe it kept re-declaring the #taskids user variable and mysql gave warnings if the stored procedure was built from the workbench, but failed if the stored procedure was built by a migration.
So the correct code was
#snip#
#Note string '0' rather than 0
SET #taskids := '0';
#note casting of id and removing the select keyword before the first #taskids
update tasks set task_status = 22, task_status_note = 'Just Testing'
where loan_app_id = loanAppId AND task_status IN (22, 23, 24) AND (
#taskids := CONCAT_WS(',', cast(id as char), #taskids) );
#snip#
we are trying to declare a variable inside mysql stored procedure that has transaction implemented in it. but it seems to be giving a syntax error :
following is the syntax of the stored procedure:
CREATE PROCEDURE `sp_MarkAppointmentRefferal`(
p_AppId bigint,
p_NewLocation bigint,
p_userId bigint,
p_ReferralReason varchar(500),
p_NewLocationName varchar(100)
)
begin
declare v_OldLocation int default 0;
set v_OldLocation = (select LocationId FROM appointments where iAppID = p_AppId limit 1 );
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
select -1;
END;
START TRANSACTION;
update table
set is_referred = 1,
referred_timestamp = now(),
referral_reason = p_ReferralReason
where iAppID = p_AppId
limit 1;
-- create a new appointment for the new referred location..
insert into appointments
(vAppName, vAppType, dAppDate, vCell, iPatID, iAppStatus, iuserid, iActive,
dInsertDate, iHSID, daily_ticket_no, LocationId, visit_id, encounter_id, ReferredFrom,ReferredOPDName, opd_name )
select vAppName, vAppType, now(), vCell, iPatID, iAppStatus, p_userId,
1, now(), iHSID, fn_GenerateNextAppointmentTicket(now(),p_NewLocation) , p_NewLocation, visit_id, encounter_id+1,
(select LocationId FROM appointments where iAppID = p_AppId limit 1),
(select OPD_Name FROM appointments where iAppID = p_AppId limit 1), p_NewLocationName
FROM appointments
where iAppID = p_AppId limit 1;
select LAST_INSERT_ID();
COMMIT;
end;
the syntax checker is saying that declare command is not valid here.
have also tried to place this inside the transaction clause and similar error shows up ..
any help is appreciated..
All declare statements should be at the top of the stored procedure body. Moving DECLARE EXIT HANDLER before the SET statement should fix the problem.