I was creating the following SQL to insert 10,000,000 records into the users_bobbies table.
However, it is too slow to proceed.
How can I introduce a bulk insert into this WHILE statement?
I would appreciate it if you could tell me.
Version: MySQL5.7
drop procedure if exists insert_user_hobby_data;
DELIMITER $$
CREATE PROCEDURE insert_user_hobby_data()
BEGIN
DECLARE i INT DEFAULT 1;
SET #user_counter = 0;
WHILE #user_counter <= 9999999 DO
set #user_id = #user_counter + 1;
INSERT INTO users_bobbies (user_id, hobby_id)
VALUES (#user_id, 1);
SET #user_counter = #user_counter + 1;
END WHILE;
END$$
DELIMITER ;
CALL insert_user_hobby_data();
This code got it running.
DROP PROCEDURE IF EXISTS bulk_insert;
DELIMITER ;;
CREATE PROCEDURE bulk_insert(IN len INT, IN block INT)
BEGIN
SET #cnt = 0;
loop1: LOOP
SET #sql = 'INSERT INTO users_bobbies (user_id,hobby_id)VALUES';
SET #i = 0;
loop2: LOOP
IF #cnt >= len THEN LEAVE loop1; END IF;
SET #id = #cnt + 1;
SET #sql = CONCAT(#sql, ' (', #id, ',', #cnt+1, ')');
SET #cnt = #cnt + 1;
SET #i = #i + 1;
IF #i < block AND #cnt < len THEN SET #sql = CONCAT(#sql, ',');
ELSE LEAVE loop2; END IF;
END LOOP loop2;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP loop1;
END;;
DELIMITER ;
TRUNCATE users_bobbies; CALL bulk_insert(10000000, 1000);
Related
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
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
I am looking to automate a procedure I am handling manually now. So, I am new to stored procedures and the code below is not working.
It stops when it outputs the first set of variables of the SELECT statement. It does not do the UPDATE and does not continue with the WHILE loop. No errors are reported.
DELIMITER //
CREATE PROCEDURE ins_die_1()
BEGIN
DECLARE v_yr INT;
DECLARE v_col CHAR(10);
DECLARE v_base INT;
DECLARE v_factor INT;
DECLARE v_cf INT;
DECLARE v_fuel CHAR(10);
SET v_yr :=1;
SET v_col := '';
SET v_base := 2860;
SET v_factor := 1;
SET v_cf := 5;
SET v_fuel := 'diesel';
WHILE v_yr <= 5 DO
SET v_col := CONCAT('ins_yr',v_yr);
SELECT v_col, v_base, v_factor, v_fuel, v_cf;
UPDATE ct_insurance
SET v_col = (v_base + 1254 + (v_factor * .0032 * price ))
WHERE fuel = v_fuel
AND CF=v_cf
AND price * v_factor < 162000
AND version_id = 1746;
SET v_yr := v_yr+1;
IF v_yr = 2 THEN SET v_factor := .8;
ELSE SET v_factor := v_factor - 0.1;
END IF;
END WHILE;
END//
DELIMITER ;
I know that there is the IN construct, whereby I should enter the variables manually when calling the procedures, but that seems like an awkward solution and certainly not very efficient.
In case you wonder I have many variables, it's because this is a test procedure. Once it works, hopefully, I will expand it.
Also, I am looking for a mySql solution only, ie, no php involved.
Column names in the UPDATE statement are taken literally, variables don't substitute there. You can do it using dynamic SQL:
SET #sql = CONCAT('UPDATE ct_insurance
SET ', v_col, ' = (v_base + 1254 + (v_factor * .0032 * price ))
WHERE fuel = v_fuel
AND CF=v_cf
AND price * v_factor < 162000
AND version_id = 1746');
PREPARE stmt FROM #sql;
EXECUTE stmt;
However, you can't access procedure local variables from prepared statements (see here) so you need to use user-defined # variables.
DELIMITER //
CREATE PROCEDURE ins_die_1()
BEGIN
DECLARE v_yr INT;
DECLARE v_col CHAR(10);
SET v_yr :=1;
SET v_col := '';
SET #v_base := 2860;
SET #v_factor := 1;
SET #v_cf := 5;
SET #v_fuel := 'diesel';
SELECT v_col, #v_base, #v_factor, #v_fuel, #v_cf;
WHILE v_yr <= 5 DO
SET v_col := CONCAT('ins_yr',v_yr);
SET #sql = CONCAT('UPDATE ct_insurance
SET ', v_col, ' = (#v_base + 1254 + (#v_factor * .0032 * price ))
WHERE fuel = #v_fuel
AND CF = #v_cf
AND price * #v_factor < 162000
AND version_id = 1746');
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET v_yr := v_yr+1;
IF v_yr = 2 THEN SET v_factor := .8;
ELSE SET v_factor := v_factor - 0.1;
END IF;
END WHILE;
END//
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
Error: Result consisted of more than one row
I think the problem is with word LIMIT
Can sb help with this ?
DELIMITER $$
CREATE PROCEDURE `InsertComment`(crc int(11) unsigned, userId int, title varchar(255),
nick varchar(20), parentId int, content text)
BEGIN
DECLARE tableName VARCHAR(4);
DECLARE tbName VARCHAR(15);
DECLARE results INTEGER;
DECLARE depth integer;
DECLARE results2 INTEGER;
DECLARE resultsM INTEGER;
DECLARE commentsId INTEGER;
DECLARE CommentX INTEGER ;
DECLARE COUNTER INTEGER;
set tbName = CAST(crc AS CHAR);
set tableName = SUBSTRING(tbName, 1, 5);
CALL CreateCommentsTable(tableName);
if parentId = 0 then
SET #results2 = 0;
SET #q2 = CONCAT("SELECT commentsId INTO #results2 FROM `",tableName,"` WHERE CRC32 = ",crc," ORDER BY commentsId DESC LIMIT 1");
PREPARE stmq2 FROM #q2;
EXECUTE stmq2;
DEALLOCATE PREPARE stmq2;
SET commentsId = #results2 + 1;
SET depth = 0;
SET #results = 0;
else
SET #q2 = CONCAT("SELECT Depth INTO #results FROM `",tableName,"` WHERE CRC32 = ",crc," AND commentsId = ",parentId);
PREPARE stmq2 FROM #q2;
EXECUTE stmq2;
DEALLOCATE PREPARE stmq2;
set depth = #results;
set depth = depth + 1;
set #CommentX = 0;
SET #COUNTER = 0;
WHILE #COUNTER = 0 AND #results > -1 DO
SET #q4= CONCAT("SELECT COUNT(*) INTO #COUNTER FROM `",tableName,"` WHERE CRC32 = ",crc," AND Depth = ",#results," AND commentsId > ",parentId);
PREPARE stmq2 FROM #q4;
EXECUTE stmq2;
DEALLOCATE PREPARE stmq2;
IF #COUNTER > 0 THEN
SET #q3= CONCAT("SELECT commentsId INTO #CommentX FROM `",tableName,"` WHERE CRC32 = ",crc," AND Depth = ",#results," AND commentsId > ",parentId," ORDER BY commentsId ASC Limit 1" );
PREPARE stmq2 FROM #q3;
EXECUTE stmq2;
DEALLOCATE PREPARE stmq2;
END IF;
SET #results = #results - 1;
END WHILE;
SET #resultsM = 0;
IF #CommentX = 0 THEN
SET #q2 = CONCAT("SELECT commentsId INTO #resultsM FROM `",tableName,"` WHERE CRC32 = ",crc," ORDER BY commentsId DESC LIMIT 1");
PREPARE stmq2 FROM #q2;
EXECUTE stmq2;
DEALLOCATE PREPARE stmq2;
SET commentsId = #resultsM +1;
else
SET commentsId = #CommentX + 1;
END IF;
SET #u = CONCAT("UPDATE `",tableName,"` SET commentsId = commentsId + 1 WHERE CRC32 = ",crc," AND commentsId > ",commentsId + 1);
PREPARE stmq FROM #u;
EXECUTE stmq;
DEALLOCATE PREPARE stmq;
end if;
SET #a = CONCAT("INSERT INTO `", tableName ,"` (`Crc32`, `UserId`, `Title`, `Nick`, `CommentsId`, `Depth`, `Content`, `CommentStatus`, `ViewStatus`)
VALUES (",crc,", ",userId,", '",title,"', '",nick,"',",commentsId,", ",depth,", '",content,"', 1, 1);");
PREPARE stmi FROM #a;
EXECUTE stmi;
DEALLOCATE PREPARE stmi;
set #results = null;
set #results2 = null;
set #tableName = null;
set #tbName = null;
END
If you use Delimiter $$ then all the ; inside your stored procedure should be replaced with $$. You should also set back the delimiter to ; at the end of your command.