We are facing an issue in declaring handlers in MYSQL 5.7 stored procedure.
Using the documentation present in https://dev.mysql.com/doc/refman/5.7/en/get-diagnostics.html, I'm trying to create handler in my stored procedure to do the following:
If a duplicate key appears, log it and move on insert good row.
End of the stored proc, get me all the error and success rows inserted.
As you can see below, we don't have primary key for table, however have the unique key constraint.
Input
CALL userTableInsert('{"userid":100, "username":"Hello"}, {"userid":102, "username":"World"}, {"userid":102, "username":"World"}', #got_dups)
Expected Output
100:Hello should get inserted and 102:World should get errored out and status needs to be corrected depicted in the output of the stored procedure.
Getting ERR : 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 CONTINUE HANDLER FOR SQLEXCEPTION ...'
Table: user_table
CREATE TABLE `user_table` (
user_id int(20) NOT NULL,
user_name varchar(255) DEFAULT NULL,
created_by varchar(255) NOT NULL,
created_date date NOT NULL,
UNIQUE KEY `user_ukey` (user_id, user_name)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
===============================================
Stored Procedure
===============================================
DELIMITER $$
DROP PROCEDURE IF EXISTS schema.userTableInsert$$
CREATE PROCEDURE schema.userTableInsert(IN JSONArrayParam MEDIUMTEXT, OUT
got_dups INT)
SQL SECURITY INVOKER
BEGIN
DECLARE code CHAR(5) DEFAULT '00000';
DECLARE msg TEXT;
DECLARE rows INT;
DECLARE result TEXT;
DECLARE rowsJSON MEDIUMTEXT DEFAULT NULL;
SET rowsJSON = TRIM(JSONArrayParam);
SET rowsJSON = TRIM(LEADING '[' FROM rowsJSON);
SET rowsJSON = TRIM(TRAILING ']' FROM rowsJSON);
DROP TEMPORARY TABLE IF EXISTS rowsToUse;
CREATE TEMPORARY TABLE rowsToUse (
user_id INT NOT NULL,
user_name VARCHAR(255) DEFAULT NULL
) ENGINE=MEMORY;
WHILE (rowsJSON != '') DO
BEGIN
DECLARE rowJSON VARCHAR(4096) DEFAULT NULL;
DECLARE temp JSON;
DECLARE userid INT DEFAULT NULL;
DECLARE username VARCHAR(255) DEFAULT NULL;
SET rowJSON = CONCAT(SUBSTRING_INDEX(rowsJSON, '}', 1), '}');
SET temp = JSON_EXTRACT(rowJSON, '$.userid');
SET userid = COALESCE(IF(JSON_TYPE(temp) = 'NULL', NULL, REPLACE(temp, '\"', '')));
SET temp = JSON_EXTRACT(rowJSON, '$.username');
SET username = COALESCE(IF(JSON_TYPE(temp) = 'NULL', NULL, REPLACE(temp, '\"', '')));
INSERT INTO rowsToUse(user_id, user_name)
VALUES(userid, username);
IF LOCATE('{', rowsJSON, 2) > 0 THEN
SET rowsJSON = SUBSTRING(rowsJSON, LOCATE('{', rowsJSON, 2));
ELSE
SET rowsJSON = '';
END IF;
END;
END WHILE;
SET SQL_SAFE_UPDATES=0;
# Getting syntax error here
DECLARE CONTINUE HANDLER FOR 1062
BEGIN
GET DIAGNOSTICS CONDITION 1
code = RETURNED_SQLSTATE, msg = MESSAGE_TEXT;
END;
INSERT INTO user_table(user_id, user_name, created_by , created_date)
SELECT user_id, user_name, 'system', NOW()
FROM rowsToUse;
IF code = '00000' THEN
GET DIAGNOSTICS rows = ROW_COUNT;
SET result = CONCAT('insert succeeded, row count = ',rows);
ELSE
SET result = CONCAT('insert failed, error = ',code,', message = ',msg);
END IF;
DROP TEMPORARY TABLE IF EXISTS rowsToUse;
SET SQL_SAFE_UPDATES=1;
SELECT result;
END
$$
DELIMITER ;
==============================================================
Kindly help me on this.
What pattern to use to leave the characters between dots in string
"12395.KS_TH014.001239" so what would be left only "KS_TH014", if its dynamical var.
I tried pattern ".\K.*?(?=.)" but it doesnt work in mysql (mariadb 10.0.10 server)
There are no regex groups up and including mysql-5.7. However one can use UDF(user defined function) to achieve similar behavior:
SELECT REGEX_REPLACE(REGEX_CAPTURE_LEFTMOST('12395.KS_TH014.001239', '[[.period.]].*[[.period.]]'), '[[.period.]]', '');
The function below replaces the leftmost regex in a string:
DELIMITER $$
CREATE FUNCTION REGEX_REPLACE(var_original VARCHAR(1000), var_pattern VARCHAR(1000),
var_replacement VARCHAR(1000)) RETURNS VARCHAR(1000)
COMMENT 'Based on https://techras.wordpress.com/2011/06/02/regex-replace-for-mysql/'
BEGIN
DECLARE var_replaced VARCHAR(1000) DEFAULT var_original;
DECLARE var_leftmost_match VARCHAR(1000) DEFAULT
REGEX_CAPTURE_LEFTMOST(var_original, var_pattern);
WHILE var_leftmost_match IS NOT NULL DO
IF var_replacement <> var_leftmost_match THEN
SET var_replaced = REPLACE(var_replaced, var_leftmost_match, var_replacement);
SET var_leftmost_match = REGEX_CAPTURE_LEFTMOST(var_replaced, var_pattern);
ELSE
SET var_leftmost_match = NULL;
END IF;
END WHILE;
RETURN var_replaced;
END$$
DELIMITER ;
which depends on:
DELIMITER $$
CREATE FUNCTION REGEX_CAPTURE_LEFTMOST(var_original VARCHAR(1000), var_pattern VARCHAR(1000)) RETURNS VARCHAR(1000)
COMMENT '
Captures the leftmost substring that matches the [var_pattern]
IN [var_original], OR NULL if no match.
'
BEGIN
DECLARE var_temp_l VARCHAR(1000);
DECLARE var_temp_r VARCHAR(1000);
DECLARE var_left_trim_index INT;
DECLARE var_right_trim_index INT;
SET var_left_trim_index = 1;
SET var_right_trim_index = 1;
SET var_temp_l = '';
SET var_temp_r = '';
WHILE (CHAR_LENGTH(var_original) >= var_left_trim_index) DO
SET var_temp_l = LEFT(var_original, var_left_trim_index);
IF var_temp_l COLLATE utf8_unicode_ci REGEXP var_pattern COLLATE utf8_unicode_ci THEN
WHILE (CHAR_LENGTH(var_temp_l) >= var_right_trim_index) DO
SET var_temp_r = RIGHT(var_temp_l, var_right_trim_index);
IF var_temp_r COLLATE utf8_unicode_ci REGEXP var_pattern COLLATE utf8_unicode_ci THEN
RETURN var_temp_r;
END IF;
SET var_right_trim_index = var_right_trim_index + 1;
END WHILE;
END IF;
SET var_left_trim_index = var_left_trim_index + 1;
END WHILE;
RETURN NULL;
END$$
DELIMITER ;
I am Trying to create stored procedure in MYSQLand getting below error.
I googled about it but no solution found please help me in this.
DELIMITER //
CREATE OR REPLACE PROCEDURE P_PROCESS_USER_STG ( OUT O_error_msg VARCHAR(3000),
OUT O_status VARCHAR(300),
IN I_uploaded_by INT (10))
BEGIN
declare L_program_name VARCHAR(100);
declare L_login_id INT(10) ;
declare L_password VARCHAR(100);
declare L_first_name VARCHAR(100);
declare L_last_name VARCHAR(100);
declare L_privilege_group_id INT(10) ;
declare L_group_id INT(10) ;
declare L_message VARCHAR(100);
declare L_date_of_upload TIMESTAMP ;
declare L_date_of_update TIMESTAMP ;
declare L_uploaded_by INT(10) ;
declare L_status VARCHAR(10) ;
declare L_error_msg VARCHAR(100),
declare L_finished INT(1) DEFAULT 0;
declare C_user_stg CURSOR FOR
SELECT LOGIN_ID,
PASSWORD,
FIRST_NAME,
LAST_NAME,
PRIVILEGE_GROUP_ID,
GROUP_ID
FROM uploaded_user_stg
where UPLOADED_BY = I_uploaded_by
and status in ( 'NEW' , 'UPDATE' );
declare CONTINUE HANDLER
FOR NOT FOUND SET L_finished = 1;
OPEN C_user_stg;
get_user: LOOP
FETCH C_user_stg INTO L_login_id ,
L_password ,
L_first_name ,
L_last_name ,
L_privilege_group_id,
L_group_id ;
IF L_finished = 1 THEN
LEAVE get_user;
END IF;
-- build email list
CALL P_CREATE_USER ( L_message ,
L_status ,
L_login_id ,
L_password ,
L_first_name,
L_last_name ,
L_privilege_group_id,
L_group_id )
UPDATE uploaded_user_stg
SET status = L_status,
error_msg = L_message
date_of_update = now();
where login_id = L_login_id;
END LOOP get_email;
CLOSE get_user;
END//
DELIMITER ;
I am getting Below error :
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that on for the right syntax to use near '
declare L_finished INT(1) DEFAULT 0;
declare C_' at line 18
Change this from:
declare L_error_msg VARCHAR(100),
to
declare L_error_msg VARCHAR(100);
DELIMITER $$
USE `g4winners2`$$
DROP PROCEDURE IF EXISTS `wagerMigration`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `wagerMigration`()
BEGIN
DECLARE tbrace_done, tbrunner_done BOOLEAN DEFAULT FALSE;
DECLARE race_card_id INT(10);
DECLARE race_number INT(10);
DECLARE day_evening VARCHAR(10) ;
DECLARE locale_type VARCHAR(50) ;
DECLARE course_surface VARCHAR(8) ;
DECLARE distance_unit VARCHAR(8) ;
DECLARE race_type VARCHAR(50) ;
DECLARE sex_restriction VARCHAR(8) ;
DECLARE age_restriction VARCHAR(8) ;
DECLARE purse_usa DECIMAL(18,2) ;
DECLARE maximum_claim_price DECIMAL(9,2) ;
DECLARE race_name VARCHAR(120) ;
DECLARE race_condition VARCHAR(255) ;
DECLARE condition_text TEXT ;
DECLARE post_time TIME ;
DECLARE race_date TIMESTAMP;
DECLARE is_active TINYINT(1) ;
DECLARE race_status_type INT(11) ;
DECLARE gait VARCHAR(50) ;
DECLARE field_size SMALLINT(6);
DECLARE weather VARCHAR(25);
DECLARE comments VARCHAR(128);
DECLARE odds_updated DATETIME;
DECLARE pools_updated DATETIME;
DECLARE win_pool_total INT(11);
DECLARE plc_pool_total INT(11);
DECLARE shw_pool_total INT(11);
declare horse_name varchar(50);
declare foaling_area char(3);
declare color varchar(255);
declare sex varchar(255);
declare breeder_name varchar(255);
declare sire_name varchar(255);
declare post_position int(10);
declare program_number varchar(255);
declare weight_carried int(10);
declare scratch_indicator varchar(255);
declare trainer_first_name varchar(255);
declare owner_name varchar(255) ;
declare jockey_first_name varchar(255);
declare odds varchar(255) ;
declare owner_silks varchar(255);
declare live_odds varchar(255);
declare is_visible tinyint(10);
declare finish_position smallint(6);
declare dead_heat_flag smallint(6);
declare distance_from_winner smallint(6);
declare win_pool int(11);
declare plc_pool int(11);
declare shw_pool int(11);
DECLARE curRace CURSOR FOR SELECT ee.event_number,"wer",'en_us',ee.surface,ee.distance,ee.race_type_text,ee.sex_restriction ,ee.age_restriction,
ee.purse,ee.max_claiming_price,ee.event_name,ee.race_conditions1,ee.track_conditions,ee.post_time,ee.raceday,ee.confirmed_flag,ee.status,ee.gait,
ee.field_size,ee.weather,ee.comments,ee.odds_updated,ee.pools_updated,ee.win_pool_total,ee.plc_pool_total,ee.shw_pool_total
FROM ebet.events ee ,ebet.race_meetings trc
WHERE trc.meeting_number=ee.meeting_number
AND trc.raceday=ee.raceday;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET tbrace_done = TRUE;
OPEN curRace;
cur_race_loop: LOOP
FETCH FROM curRace INTO race_number ,day_evening ,locale_type,course_surface,distance_unit,race_type,sex_restriction ,age_restriction
,purse_usa ,maximum_claim_price ,race_name ,race_condition ,condition_text
,post_time ,race_date ,is_active ,race_status_type ,gait
,field_size,weather,comments,odds_updated,pools_updated,win_pool_total,plc_pool_total,shw_pool_total;
IF tbrace_done THEN
CLOSE curRace;
LEAVE cur_race_loop;
END IF;
SET FOREIGN_KEY_CHECKS=0;
INSERT INTO g4winners2.tb_races(race_number ,day_evening ,locale_type,course_surface,distance_unit,race_type,sex_restriction ,age_restriction
,purse_usa ,maximum_claim_price ,race_name ,race_condition ,condition_text
,post_time ,race_date ,is_active ,race_status_type ,gait
,field_size,weather,comments,odds_updated,pools_updated,win_pool_total,plc_pool_total,shw_pool_total)
VALUES (race_number ,day_evening ,locale_type,course_surface,distance_unit,race_type,sex_restriction ,age_restriction
,purse_usa ,maximum_claim_price ,race_name ,race_condition ,condition_text
,post_time ,race_date ,is_active ,race_status_type ,gait
,field_size,weather,comments,odds_updated,pools_updated,win_pool_total,plc_pool_total,shw_pool_total);
SET FOREIGN_KEY_CHECKS=1;
SET #ID:=(SELECT LAST_INSERT_ID());
SELECT CONCAT ("Result :**", #ID, " ") AS '';
SET FOREIGN_KEY_CHECKS=0;
BLOCK2: BEGIN
DECLARE curRunner CURSOR FOR SELECT er.runner_name,er.area_foaled,er.color,er.sex,er.breeder,er.sire,er.post_position,er.program_number ,er.weight,
er.scratched_flag,er.trainer,er.owner,er.jockey,er.morning_line_odds,er.silks,er.current_odds,'1', er.finish_position,er.dead_heat_flag
,er.distance_from_winner,er.win_pool,er.plc_pool,er.shw_pool FROM ebet.runners er ,ebet.events ee
WHERE
ee.meeting_number=er.meeting_number
AND ee.event_number=er.event_number
AND ee.raceday=er.raceday;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET tbrunner_done = TRUE;
OPEN curRunner;
cur_runner_loop: LOOP
FETCH curRunner INTO horse_name,foaling_area,color,sex,breeder_name,sire_name,post_position,program_number,weight_carried,scratch_indicator,trainer_first_name,owner_name,jockey_first_name,odds,owner_silks,live_odds,is_visible,finish_position,dead_heat_flag,distance_from_winner,win_pool,plc_pool,shw_pool;
IF tbrace_done THEN
set tbrace_done = false;
CLOSE curRunner;
LEAVE cur_runner_loop;
END IF;
INSERT INTO g4winners2.tb_race_runners(race_id,horse_name,foaling_area,color,sex,breeder_name,sire_name,post_position,program_number ,
weight_carried,scratch_indicator ,trainer_first_name ,owner_name ,jockey_first_name,odds ,owner_silks ,live_odds ,is_visible
,finish_position,dead_heat_flag,distance_from_winner,win_pool,plc_pool,shw_pool
) values(#ID,horse_name,foaling_area,color,sex,breeder_name,sire_name,post_position,program_number ,
weight_carried,scratch_indicator ,trainer_first_name ,owner_name ,jockey_first_name,odds ,owner_silks ,live_odds ,is_visible
,finish_position,dead_heat_flag,distance_from_winner,win_pool,plc_pool,shw_pool);
END LOOP cur_runner_loop;
END BLOCK2;
END LOOP cur_race_loop;
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 '' at line 118 (0 ms taken)
Could it be a false error as it can not compile as you have no "END" to the overall procedure?. You close out your loops and block, but not the procedure.