i want to split my row something like this:
example:
id data
1 23#4#
2 2#4#5#
to be like this
id data
1 23
1 4
2 2
2 4
2 5
i have looking for this problem in stack overflow but the solution is not satisfaction me. please help me.
i try to make a store procedure in mysql, the code it's ok no error, but the result is not ok.
drop procedure if exists pecah_lokasi_sp;
create procedure pecah_lokasi_sp()
begin
DECLARE ii INT;
DECLARE ki varchar(255);
DECLARE ulang int DEFAULT 1;
DECLARE hasil varchar(255) DEFAULT '';
DECLARE selesai INT DEFAULT FALSE;
DECLARE kursor CURSOR FOR
SELECT id_iklan, lokasi_kerja_utama
FROM iklan_lowongan_tb
WHERE status = 'Aktif';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET selesai = TRUE;
DELETE FROM temp_lok_tb;
OPEN kursor;
read_loop: LOOP
FETCH kursor INTO ii, ki;
IF selesai THEN
LEAVE read_loop;
END IF;
WHILE (ulang < LENGTH(ki)) DO
IF SUBSTRING(ki, ulang, 1) <> '#' THEN
SET hasil = CONCAT(hasil, SUBSTRING(ki, ulang, 1));
ELSE
INSERT INTO temp_lok_tb (id_iklan, id_kota) VALUES(ii, hasil);
SET hasil = '';
END IF;
SET ulang = ulang+1;
END WHILE;
SET ulang = 1;
END LOOP read_loop;
CLOSE kursor;
select * from temp_lok_tb;
end;
i think i can solve my problem myself.
this is my revision code, the result is true.
drop procedure if exists pecah_lokasi_sp;
create procedure pecah_lokasi_sp()
begin
DECLARE ii INT;
DECLARE ki varchar(255);
DECLARE ulang int DEFAULT 1;
DECLARE hasil varchar(255) DEFAULT '';
DECLARE selesai INT DEFAULT FALSE;
DECLARE jmlkarakter int;
DECLARE kursor CURSOR FOR
SELECT id_iklan, lokasi_kerja_utama
FROM iklan_lowongan_tb
WHERE status = 'Aktif';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET selesai = TRUE;
DELETE FROM temp_lok_tb;
OPEN kursor;
read_loop: LOOP
FETCH kursor INTO ii, ki;
IF selesai THEN
LEAVE read_loop;
END IF;
SET jmlkarakter = LENGTH(ki) - LENGTH(REPLACE(ki, '#', '')) ;
WHILE (ulang <= jmlkarakter) DO
IF ulang = 1 THEN
INSERT INTO temp_lok_tb(id_iklan, id_kota) VALUES(ii, SUBSTRING_INDEX(ki,'#',1));
ELSE
INSERT INTO temp_lok_tb(id_iklan, id_kota) VALUES(ii, SUBSTRING_INDEX(SUBSTRING_INDEX(ki,'#', ulang),'#',-1));
END IF;
SET ulang = ulang+1;
END WHILE;
SET ulang = 1;
END LOOP read_loop;
CLOSE kursor;
select * from temp_lok_tb;
end;
Related
THE CURSOR IS NOT GOING TO THE ELSE STATEMENT. WHAT AM I DOING WRONG? HOW CAN I DEBUG IN MYSQL ?
I am trying to get the list of task Ids with null values and then for each taskID, I am calling a SP to create start data and due date of the missing tasks(greater than the max(start_date available) until the current_date
DROP PROCEDURE IF EXISTS zcursor_ADDTA1;
DELIMITER ;;
CREATE PROCEDURE zcursor_ADDTA1(
#out retCount int
)
BEGIN
#DECLARE C_ID INT;
DECLARE C_TASK_ID INT;
DECLARE C_pattern varchar(100);
DECLARE C_REM INT;
DECLARE ACT_T_STTM VARCHAR(100);
DECLARE ACT_T_DTTM VARCHAR(100);
DECLARE TZ VARCHAR(100);
DECLARE T_STDT DATE;
DECLARE T_EXDT DATE;
DECLARE retCount INT;
DECLARE done INT DEFAULT FALSE;
DECLARE TA_MAX_ST_DT DATE;
#DECLARE P1 INT;
DECLARE cursor_i CURSOR FOR SELECT TASK_ID, PATTERN, reminder_days_before, ACTUAL_TASK_START_TIME,ACTUAL_TASK_DUE_TIME,TIMEZONE,
START_DT,EXP_DT FROM OCC_ML_TASK_RECURRENCE TR WHERE PATTERN = 'DAILY' AND CALENDAR_TYPE='' AND IS_CANCELED =0 AND EXP_DT>CURRENT_DATE();
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET retCount = 0;
OPEN cursor_i;
read_loop: LOOP
FETCH NEXT FROM cursor_i INTO C_TASK_ID,C_pattern,C_REM,ACT_T_STTM,ACT_T_DTTM,
TZ,T_STDT,T_EXDT;
IF done THEN
LEAVE read_loop;
ELSE
SELECT MAX(TA.START_DTM)FROM
OCC_ML_TASK_ACTIVITY TA
WHERE TA.TASK_ID=C_TASK_ID INTO TA_MAX_ST_DT;
SELECT DATE_ADD(TA_MAX_ST_DT,INTERVAL 1 DAY) INTO TA_MAX_ST_DT;
WHILE (TA_MAX_ST_DT<=CURRENT_DATE())
DO
BEGIN
IF WEEKDAY(TA_MAX_ST_DT)=4 THEN
CALL ZTA_MISSINGDATA_INSERT(C_TASK_ID ,TA_MAX_ST_DT);
SELECT DATE_ADD(TA_MAX_ST_DT,INTERVAL 3 DAY)INTO TA_MAX_ST_DT;
ELSEIF WEEKDAY(TA_MAX_ST_DT)=5 THEN
#"NO INSERT "
SELECT DATE_ADD(TA_MAX_ST_DT,INTERVAL 2 DAY)INTO TA_MAX_ST_DT;
ELSEIF WEEKDAY(TA_MAX_ST_DT)=6 THEN
#"NO INSERT "
SELECT DATE_ADD(TA_MAX_ST_DT,INTERVAL 1 DAY)INTO TA_MAX_ST_DT;
ELSE
CALL ZTA_MISSINGDATA_INSERT(C_TASK_ID ,TA_MAX_ST_DT);
SELECT DATE_ADD(TA_MAX_ST_DT,INTERVAL 1 DAY) INTO TA_MAX_ST_DT;
END IF;
END;
END WHILE;
END IF;
END LOOP;
CLOSE cursor_i;
END;
;;
Please note the first cursor fetches 3 results and when I insert it inserts only 1. Earlier when I did not have open curs2, it was functioning fine, but now it doesn't. I might have missed some with done and done2 variables as I am writing a stored procedure after a long time. Please see if you may find anything wrong.
Thanks
BLOCK1: begin
declare done INT DEFAULT FALSE;
declare gid BIGINT;
declare activity_name VARCHAR(255) ;
declare type_1 VARCHAR(255) ;
declare shop_activity_id BIGINT;
declare curs CURSOR for select id, activityName, `Type`, shopActivityId from gantttask where `Type` = 'Project';
open curs;
LOOP1: loop
fetch curs into gid, activity_name, type_1, shop_activity_id;
if done then
leave LOOP1;
end if;
insert into gantttask_result VALUES (gid, activity_name, type_1, shop_activity_id);
BLOCK2: begin
declare done2 INT DEFAULT FALSE;
declare gid2 BIGINT;
declare activity_name2 VARCHAR(255) ;
declare type_2 VARCHAR(255) ;
declare shop_activity_id2 BIGINT;
declare curs2 CURSOR for select id, activityName, `Type`, shopActivityId from gantttask where `Type` != 'Project' and shopActivityId = shop_activity_id order by id;
open curs2;
LOOP2: loop
fetch curs2 into gid2, activity_name2, type_2, shop_activity_id2;
if done2 then
leave LOOP2;
end if;
end loop LOOP2;
close curs2;
end BLOCK2;
end loop LOOP1;
close curs;
end BLOCK1
DELIMITER $$
CREATE PROCEDURE `remove_schedule_duplicate` ()
BEGIN
BLOCK1 : BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE schedule_id CHAR(36);
DECLARE gamePk INTEGER;
DECLARE keep_entry TINYINT(1);
DECLARE scheduleDuplicate CURSOR FOR SELECT game_pk FROM schedule where is_active = 1 group by game_pk,home_team_id,away_team_id,venue_id having count(game_pk) > 1 limit 2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN scheduleDuplicate;
get_schedule_duplicate: LOOP
FETCH scheduleDuplicate INTO gamePk;
IF finished = 1 THEN
LEAVE get_schedule_duplicate;
END IF;
**BLOCK2 : BEGIN
DECLARE block_finished INTEGER DEFAULT 0;
DECLARE blockDuplicate CURSOR FOR SELECT id FROM schedule where game_pk = gamePk and is_active = 1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET block_finished = 1;
OPEN blockDuplicate;
block_schedule_duplicate: LOOP
FETCH blockDuplicate INTO schedule_id;
IF block_finished = 1 THEN
LEAVE block_schedule_duplicate;
END IF;
IF keep_entry = 0 THEN
UPDATE schedule set is_active = 0 where id = schedule_id;
END IF;
END LOOP block_schedule_duplicate;
CLOSE blockDuplicate;
END BLOCK2;**
END LOOP get_schedule_duplicate;
CLOSE scheduleDuplicate;
END BLOCK1;
END
$$
The problem is Innerloop first time execute well after that block_finished always be 1 so. always it quits the inner block.
How to resolve this issue. What i do ? Some one help me to resolve the issue.
I have Changed My Stored procedure like this:
DELIMITER $$
CREATE PROCEDURE `remove_schedule_duplicate`()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE schedule_id,temp CHAR(36) DEFAULT NULL;
DECLARE gamePk INTEGER;
DECLARE keep_entry TINYINT(1);
DECLARE scheduleDuplicate CURSOR FOR SELECT game_pk,id FROM schedule where game_pk in (SELECT game_pk FROM schedule where is_active = 1 group by game_pk,home_team_id,away_team_id,venue_id having count(game_pk) > 1) and is_active = 1 order by game_pk;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN scheduleDuplicate;
get_schedule_duplicate: LOOP
FETCH scheduleDuplicate INTO gamePk,schedule_id;
IF finished = 1 THEN
LEAVE get_schedule_duplicate;
END IF;
IF ((temp IS NULL) AND (gamePk IS NOT NULL)) OR ((temp IS NOT NULL) AND (temp <> gamePk)) THEN
SET temp = gamePk;
SET keep_entry = 1;
#ELSE IF temp IS NOT NULL AND temp = gamePk THEN
ELSE
SET keep_entry = 0;
END IF;
IF keep_entry = 0 THEN
UPDATE schedule set is_active = 0 where id = schedule_id;
END IF;
END LOOP get_schedule_duplicate;
CLOSE scheduleDuplicate;
END$$
DELIMITER ;
How to use for loop in MySQL data set ?
FOR x IN (SELECT column FROM table_name WHERE column_2 = input_val)
LOOP
sum_total := sum_total + x.column ;
END LOOP;
This is an example how I used to loop data set in oracle.
How can this be achieved in MySql ?
How about not looping at all. It's SQL after all.
SELECT SUM(`column`) total
FROM table_name
WHERE column_2 = <input_val>
Otherwise use CURSOR
Now, equivalent loop using CURSOR will look like
DELIMITER $$
CREATE PROCEDURE sp_loop(IN input_val INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE sum_current, sum_total INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT column1 FROM table_name WHERE column2 = input_val;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO sum_current;
IF done THEN
LEAVE read_loop;
END IF;
SET sum_total = sum_total + sum_current;
END LOOP;
CLOSE cur1;
SELECT sum_total;
END$$
DELIMITER ;
Here is SQLFiddle
DROP PROCEDURE IF EXISTS `foo`.`usp_cursor_example`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `foo`.`usp_cursor_example`(
IN name_in VARCHAR(255)
)
READS SQL DATA
BEGIN
DECLARE name_val VARCHAR(255);
DECLARE status_update_val VARCHAR(255);
-- Declare variables used just for cursor and loop control
DECLARE no_more_rows BOOLEAN;
DECLARE loop_cntr INT DEFAULT 0;
DECLARE num_rows INT DEFAULT 0;
-- Declare the cursor
DECLARE friends_cur CURSOR FOR
SELECT
name
, status_update
FROM foo.friend_status
WHERE name = name_in;
-- Declare 'handlers' for exceptions
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET no_more_rows = TRUE;
OPEN friends_cur;
select FOUND_ROWS() into num_rows;
the_loop: LOOP
FETCH friends_cur
INTO name_val
, status_update_val;
IF no_more_rows THEN
CLOSE friends_cur;
LEAVE the_loop;
END IF;
select name_val, status_update_val;
-- count the number of times looped
SET loop_cntr = loop_cntr + 1;
END LOOP the_loop;
-- 'print' the output so we can see they are the same
select num_rows, loop_cntr;
END
DELIMITER ;
I was trying use multiple select at one procedure to assign the value of variable.
but i got error like this "Operand should contain 1 column(s)"
this is my code :
DELIMITER $$
DROP PROCEDURE IF EXISTS `bankdb`.`charge` $$
CREATE PROCEDURE `bankdb`.`charge` ()
BEGIN
DECLARE idcust_val INT;
DECLARE balance_val FLOAT;
DECLARE balance_val1 FLOAT;
DECLARE balance_val2 FLOAT;
DECLARE productCd_val VARCHAR(10);
DECLARE productType_val VARCHAR(10);
DECLARE no_more_rows INT DEFAULT 0;
DECLARE num_rows INT DEFAULT 0;
DECLARE col_cur CURSOR FOR
select a.cust_id, a.avail_balance, a.product_cd, p.product_type_cd
from account a, product p
where a.product_cd = p.product_cd;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_rows = 1;
OPEN col_cur;
select FOUND_ROWS() into num_rows;
read_loop: LOOP
IF no_more_rows THEN
CLOSE col_cur;
LEAVE read_loop;
END IF;
FETCH col_cur INTO idcust_val, balance_val, productCd_val, productType_val;
SELECT idcust_val, balance_val, productCd_val;
IF productType_val = 'ACCOUNT' THEN
IF productCd_val = 'SAV' || productCd_val = 'CD' THEN
IF balance_val < 2000 THEN
SELECT (balance_val-10) INTO balance_val;
END IF;
ELSE
SELECT (balance_val+(balance_val*0,05)) INTO balance_val;
END IF;
ELSE
SELECT (balance_val-(balance_val*0,1)) INTO balance_val;
END IF;
/*UPDATE account SET avail_balance = balance_val WHERE account_id = idcust_val;*/
END LOOP read_loop;
END $$
DELIMITER ;
please help!
Change decimal point ',' to '.'
0,05 -> 0.05
0,1 - 0.1