How to Execute Dynamic Sql String as a Query in mysql server? - mysql

I have create a trigger which is create a dynamic query.and execute it i had tried 'EXECU q' but it does not work. how can i run/execute that dynamic query.
BEGIN
DECLARE a INT Default 0 ;
DECLARE str VARCHAR(255);
DECLARE q VARCHAR(500);
SET q = 'insert into '+new.master_name+' values(';
simple_loop: LOOP
SET a=a+1;
SET str = SPLIT_STRING(new.remarks,"|",a);
SET q = CONCAT(q,str+',');
SET q = LEFT(q, LENGTH(q) - 1);
IF str='' THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
SET q = CONCATE(q,');');
EXEC q
END
This is Trigerr
this is Function which i made
RETURN REPLACE(
SUBSTRING(
SUBSTRING_INDEX(str , delim , pos) ,
CHAR_LENGTH(
SUBSTRING_INDEX(str , delim , pos - 1)
) + 1
) ,
delim ,
''
)

I've written a stored procedure to execute dynamically constructed sql statements.
Usage
SET #index := 7;
CALL eval(CONCAT('SELECT ', #index));
Implementation
DELIMITER $$
CREATE PROCEDURE eval(IN dynamic_statement TEXT)
BEGIN
SET #dynamic_statement := dynamic_statement;
PREPARE prepared_statement FROM #dynamic_statement;
EXECUTE prepared_statement;
DEALLOCATE PREPARE prepared_statement;
END$$
DELIMITER ;

From my understanding you must make a prepared statement from your string first in order to execute it. So the following partial code should work in replacement for just EXEC q:
PREPARE thequery FROM q;
EXECUTE thequery;

use prepare statement to execute your dynamic query
BEGIN
DECLARE a INT Default 0 ;
DECLARE str VARCHAR(255);
DECLARE q VARCHAR(500);
DECLARE q1 VARCHAR(500);
DECLARE q2 VARCHAR(500);
SET #q = 'insert into '+new.master_name+' values(';
simple_loop: LOOP
SET a=a+1;
SET str = SPLIT_STRING(new.remarks,"|",a);
SET q = CONCAT(#q,str+',');
SET q1 = LEFT(q, LENGTH(q) - 1);
IF str='' THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
SET q2 = CONCATE(q1,');');
PREPARE stmt FROM q2;
EXECecute stmt;
deallocate PREPARE stmt;
END

Related

MySQL - INSERT INTO SELECT using subqueries for the column names and values [duplicate]

I have create a trigger which is create a dynamic query.and execute it i had tried 'EXECU q' but it does not work. how can i run/execute that dynamic query.
BEGIN
DECLARE a INT Default 0 ;
DECLARE str VARCHAR(255);
DECLARE q VARCHAR(500);
SET q = 'insert into '+new.master_name+' values(';
simple_loop: LOOP
SET a=a+1;
SET str = SPLIT_STRING(new.remarks,"|",a);
SET q = CONCAT(q,str+',');
SET q = LEFT(q, LENGTH(q) - 1);
IF str='' THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
SET q = CONCATE(q,');');
EXEC q
END
This is Trigerr
this is Function which i made
RETURN REPLACE(
SUBSTRING(
SUBSTRING_INDEX(str , delim , pos) ,
CHAR_LENGTH(
SUBSTRING_INDEX(str , delim , pos - 1)
) + 1
) ,
delim ,
''
)
I've written a stored procedure to execute dynamically constructed sql statements.
Usage
SET #index := 7;
CALL eval(CONCAT('SELECT ', #index));
Implementation
DELIMITER $$
CREATE PROCEDURE eval(IN dynamic_statement TEXT)
BEGIN
SET #dynamic_statement := dynamic_statement;
PREPARE prepared_statement FROM #dynamic_statement;
EXECUTE prepared_statement;
DEALLOCATE PREPARE prepared_statement;
END$$
DELIMITER ;
From my understanding you must make a prepared statement from your string first in order to execute it. So the following partial code should work in replacement for just EXEC q:
PREPARE thequery FROM q;
EXECUTE thequery;
use prepare statement to execute your dynamic query
BEGIN
DECLARE a INT Default 0 ;
DECLARE str VARCHAR(255);
DECLARE q VARCHAR(500);
DECLARE q1 VARCHAR(500);
DECLARE q2 VARCHAR(500);
SET #q = 'insert into '+new.master_name+' values(';
simple_loop: LOOP
SET a=a+1;
SET str = SPLIT_STRING(new.remarks,"|",a);
SET q = CONCAT(#q,str+',');
SET q1 = LEFT(q, LENGTH(q) - 1);
IF str='' THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
SET q2 = CONCATE(q1,');');
PREPARE stmt FROM q2;
EXECecute stmt;
deallocate PREPARE stmt;
END

MySQL Stored Procedure Cursor example

following code is running fine, what I need to ask how can I use a variable instead of a table name written in cursor select statement?
block5: begin
declare var1 int default 0;
DECLARE done TINYINT DEFAULT FALSE;
DECLARE cursor1 CURSOR FOR SELECT co_srno FROM vu_company where katscode in ('OGDC', 'LUCK', 'MCB');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor1;
my_loop: LOOP
FETCH cursor1 INTO var1;
IF done THEN
LEAVE my_loop;
ELSE
set #s = concat("insert into ", #temp_table_name_scrnr_data, " (sr_no) values (", var1, ")");
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END LOOP;
end block5;

Concatenate and Execute Statement Procedure in MySQL

I'm trying to create and use this procedure:
delimiter //
CREATE PROCEDURE doiterate(p1 INT)
BEGIN
DECLARE str VARCHAR(5000);
label1: LOOP
SET #query = 'SELECT * FROM ';
IF p1 > 0 THEN
SET #query = CONCAT(#query, ' wp_', pl, '_options,');
ITERATE label1;
END IF;
LEAVE label1;
END LOOP label1;
SET #query = substring(#query,1,length(#query)-1);
SET #query = CONCAT(#query, ' WHERE option_name = \'template\'OR option_name = \'stylesheet\' OR option_name = \'current_theme\'');
PREPARE stmt FROM #query;
EXECUTE stmt;
END//
and when I execute it I get this message:
Unknown column 'pl' in 'field list'
Can anyone point where did I do wrong?
You have a typo in your code:
SET #query = CONCAT(#query, ' wp_', pl, '_options,');
should be
SET #query = CONCAT(#query, ' wp_', p1, '_options,');
You have used "PL" (capitals to emphasize) instead of "p1";

Using prepared statements with cursor

I put the cursor declaration in the prepared statement and then executed it, then returns an error #1324 - Undefined CURSOR: getid.
How do I solve this problem?
delimiter ;;
drop procedure if exists test2;;
create procedure test2(table_id VARCHAR(25))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE id INT;
DECLARE id_new INT;
DECLARE stmt1 VARCHAR(1024);
DECLARE stmt2 VARCHAR(1024);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
SET #sqltext1 := CONCAT('DECLARE getid CURSOR FOR SELECT entryId FROM ',table_id,' ORDER BY entryId');
PREPARE stmt1 FROM #sqltext1;
EXECUTE stmt1;
SET #id_new = 1;
OPEN getid;
FETCH getid into id;
REPEAT
SET #sqltext2 := CONCAT('UPDATE ',table_id,' SET entryId = ? WHERE entryId = ?');
PREPARE stmt2 FROM #sqltext2;
EXECUTE stmt2 USING #new_id, id;
SET #id_new = #id_new + 1;
FETCH getid into id;
UNTIL done END REPEAT;
CLOSE getid;
END
;;
CALL test2('Test');
Some rules:
All declarations must be at one place in a sequence.
You can't use variable names in cursor declarations.
Handler declarations must be after cursor declarations.
You can't use local variable names (id) as bound parameters for
prepared statements. You can only use session variables (say #_id).
To overcome such problems, you can adopt following solution.
Define a temporary table using the input parameter to the SP.
Now declare the cursor on the same table and use it.
Drop the temporary table created.
Following example should work on your tables.
delimiter $$
drop procedure if exists test2$$
create procedure test2( table_id varchar(25) )
begin
set #temp_query = 'drop temporary table if exists temp_cursor_table';
prepare pst from #temp_query;
execute pst;
drop prepare pst; -- or
-- deallocate prepare pst;
set #temp_table_query='create temporary table temp_cursor_table ';
set #temp_table_query=concat( #temp_table_query, ' select entryId from ' );
set #temp_table_query=concat( #temp_table_query, table_id );
set #temp_table_query=concat( #temp_table_query, ' order by entryId' );
prepare pst from #temp_table_query;
execute pst;
drop prepare pst;
-- now write your actual cursor and update statements
-- in a separate block
begin
declare done int default false;
declare id int;
declare id_new int;
declare stmt1 varchar(1024);
declare stmt2 varchar(1024);
declare getid cursor for
select entryId from temp_cursor_table order by entryId;
declare continue handler for not found set done = 1;
set #id_new = 1;
open getid;
fetch getid into id;
repeat
set #sqltext2 := concat( 'update ', table_id );
set #sqltext2 := concat( #sqltext2, ' set entryId = ? where entryId = ?' );
set #_id = id;
prepare stmt2 from #sqltext2;
execute stmt2 using #new_id, #_id;
set #id_new = #id_new + 1;
fetch getid into id;
until done end repeat;
close getid;
end;
end;
$$
delimiter ;
Now call the procedure with table_id value.
call test2( 'Test' );

Mysql Procedure. Update and Select

I have a procedure call that updates a set of data and then returns the data set for my to render. Everything works fine except that, I cant do both operations at once. If I do the update, then the procedure, won´t return any value and vice versa. I have seen some answers suggesting to use temptables but I could not find how to retrieve the dataset. I appreciate any help even if it comes to improving my query.
CREATE DEFINER=`root`#`localhost` PROCEDURE `prueba`(IN `idUsuario` INT)
MODIFIES SQL DATA
BEGIN
DECLARE flag INT DEFAULT FALSE;
DECLARE done INT DEFAULT FALSE;
DECLARE idNotificacion INT DEFAULT 0;
DECLARE cont INT DEFAULT 0;
DECLARE resultset CURSOR FOR SELECT id FROM notificaciones WHERE involvedA_idUsuario=idUsuario AND active=1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN resultset;
SET #query = "SELECT * FROM notificaciones n WHERE n.id IN('null'";
the_loop: LOOP
FETCH resultset INTO idNotificacion;
IF done THEN
LEAVE the_loop;
END IF;
SET cont = cont + 1;
SET flag = TRUE;
SET #query = CONCAT(#query," , " ,idNotificacion);
UPDATE notificaciones SET active=0 WHERE id=idNotificacion;
END LOOP the_loop;
CLOSE resultset;
IF flag THEN
SET #query = CONCAT(#query, ")");
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END
Do you really need a cursor? An option like this, maybe it can be useful:
/* Procedure structure for procedure `prueba` */
/*!50003 DROP PROCEDURE IF EXISTS `prueba` */;
DELIMITER $$
CREATE PROCEDURE `prueba`(`idusuario` INT)
BEGIN
DECLARE `ids` LONGTEXT DEFAULT NULL;
SELECT GROUP_CONCAT(`id`) INTO `ids`
FROM `notificaciones`
WHERE `involveda_idusuario` = `idusuario` AND `active` = 1;
IF (`ids` IS NOT NULL) THEN
SET #`stmt` := CONCAT('UPDATE `notificaciones`
SET `active` = 0
WHERE `id` IN (', `ids`, ')');
PREPARE `exec` FROM #`stmt`;
EXECUTE `exec`;
SET #`stmt` := CONCAT('SELECT `id`, `involveda_idusuario`, `active`
FROM `notificaciones` `n`
WHERE `n`.`id` IS NULL OR `n`.`id` IN (', `ids`, ')');
PREPARE `exec` FROM #`stmt`;
EXECUTE `exec`;
DEALLOCATE PREPARE `exec`;
END IF;
END$$
DELIMITER ;
You must be careful with GROUP_CONCAT and the system variable group_concat_max_len.
SQL Fiddle demo