I am writing a stored procedure, which opens a cursor to a table, and then iterate through all records. In the iterating process I create a dynamic query based on the results of the first cursor.
I need to open the cursor on dynamic SQL, but MySQL is not allowing me to do so. According to the official doc of MySQL: "Cursors must be declared before declaring handlers. Variables and conditions must be declared before declaring either cursors or handlers".
Here is the script:
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_test$$
CREATE PROCEDURE `sp_test`()
BEGIN
-- Declarations
DECLARE prepared_sql VARCHAR(1000);
DECLARE index_count INT;
-- Cursors
DECLARE cursor1 CURSOR FOR SELECT * from table1;
-- Continue Handler for Cursor
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_rows = TRUE;
-- Open cursors
OPEN cursor1;
-- Business Logic
all_alerts_loop: LOOP
-- Fetch record from cursor1 and create a dynamic sql
-- Check if cursor has reached to end than leave the loop
IF no_more_rows THEN
LEAVE all_alerts_loop;
END IF;
WHILE @some_other_variable <> 0
DO
-- I want to open cursor 2 on this sql
-- set @prepared_sql = 'create dynamic sql here';
END WHILE;
-- This works fine
PREPARE stmt FROM @prepared_sql;
EXECUTE stmt;
-- But can't define cursor here? so what is the solution
-- Gives syntax error, I have tried with @prepared_sql also rather than stmt
DECLARE cursor2 CURSOR FOR stmt;
END LOOP;
-- closing cursors
CLOSE cursor1;
END$$
DELIMITER ;
Any idea on how to create cursor for a dynamic query? in MySQL?
It's not allowed a DEFINE cur CURSOR FOR prepared_statement, you must define a valid SQL statement. The good news is that you can define the cursor on a view that can be dynamically created later. For example...
DROP PROCEDURE IF EXISTS my_dynamic_proc;
DELIMITER //
CREATE PROCEDURE my_dynamic_proc(tablename varchar(64), fieldname varchar(64), country VARCHAR(64))
BEGIN
DECLARE adr_value varchar(500);
DECLARE done BOOLEAN DEFAULT FALSE;
-- Cursor definition
DECLARE cur1 CURSOR FOR SELECT address FROM tmp_view_address;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- Dynamic view definition and creation
SET @v = concat('CREATE OR REPLACE VIEW tmp_view_address as SELECT `',fieldname,'` as address FROM ',tablename,' WHERE country_name = "',country,'" group by 1 order by count(1) desc');
PREPARE stm FROM @v;
EXECUTE stm;
DEALLOCATE PREPARE stm;
-- Open cursor
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO adr_value;
IF done THEN
LEAVE read_loop;
END IF;
-- Basic output result
SELECT concat("My address is ",adr_value);
-- Use every result in a dynamic update
SET @u = concat('update ',tablename,' set new_field_address = "',adr_value,'" where country_name = "',country,'" and new_field_address is null');
PREPARE stm FROM @u;
EXECUTE stm;
DEALLOCATE PREPARE stm;
END LOOP;
CLOSE cur1;
END//
DELIMITER ;
Create an another Procedure and write the code of cursor in this new procedure and then call the procedure from where u want to declare a cursor...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With