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.
Related
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);
I am working on an automatisation of queries in my database. I have 15 tables names the same way 'blablablaCOUNTRYblablabla' and i want to count the number of rows of each table and store them into an other table that actually contains just the list of the countries and and the table name.
I have decided to create a procedure
CREATE DEFINER=CURRENT USER PROCEDURE `PM`()
MODIFIES SQL DATA
BEGIN
DECLARE nom_table VARCHAR(1000);
DECLARE site_table_uniq VARCHAR(50);
DECLARE x INT;
DECLARE nb_ligne INT;
DECLARE site_coord VARCHAR(1000);
SET nom_table = "";
SET site_table_uniq = "";
SET x = 1;
SET nb_ligne = (SELECT COUNT(*) FROM SIG_PM_THERMO);
# SIG PM THERMO is the table i want to fill with the number of rows
WHILE x <= nb_ligne DO
SET site_table_uniq = (SELECT pmthermo.Site_table FROM SIG_PM_THERMO pmthermo WHERE pmthermo.Id = x);
SET #site_coord = (SELECT pmthermo.Site_coord FROM SIG_PM_THERMO pmthermo WHERE pmthermo.Id = 1) ;
SET #nom_table = (SELECT pm.Nom_table FROM SIG_PM_THERMO pm WHERE pm.Site_table = site_table_uniq );
SET #sql = CONCAT('SELECT SUM(nb_therm) FROM (SELECT COUNT(pmt.Temperature) AS nb_therm FROM ', #nom_table,' pmt WHERE pmt.Temperature !="-99" ) AS t ;');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET x = x + 1;
END WHILE;
END
This display (each value in a tab with one line) all the value i need but i don't understand how to get them and store them in my table with a condition (that the countries are the same)
Would have any idea ?
Best regards (and happy new year)
You rewrite your query a little and add a varianble that stores the data
Every loop adds the session variable #sumthermo to the tolasum which is stored in an OUT variable
CREATE DEFINER=CURRENT_USER PROCEDURE `PM`(OUT _totalsum BIGINT)
MODIFIES SQL DATA
BEGIN
DECLARE nom_table VARCHAR(1000);
DECLARE site_table_uniq VARCHAR(50);
DECLARE x INT;
DECLARE nb_ligne INT;
DECLARE site_coord VARCHAR(1000);
SET _totalsum := 0;
SET nom_table = "";
SET site_table_uniq = "";
SET x = 1;
SET nb_ligne = (SELECT COUNT(*) FROM SIG_PM_THERMO);
# SIG PM THERMO is the table i want to fill with the number of rows
WHILE x <= nb_ligne DO
SET site_table_uniq = (SELECT pmthermo.Site_table FROM SIG_PM_THERMO pmthermo WHERE pmthermo.Id = x);
SET #site_coord = (SELECT pmthermo.Site_coord FROM SIG_PM_THERMO pmthermo WHERE pmthermo.Id = 1) ;
SET #nom_table = (SELECT pm.Nom_table FROM SIG_PM_THERMO pm WHERE pm.Site_table = site_table_uniq );
SET #sql = CONCAT('SELECT SUM(nb_therm) INTO #sumthermo FROM (SELECT COUNT(pmt.Temperature) AS nb_therm FROM ', #nom_table,' pmt WHERE pmt.Temperature !="-99" ) AS t ;');
SET _totalsum := _totalsum + #sumthermo ;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET x = x + 1;
END WHILE;
END
Now you can run the query and have the value stored in another sessionvariable
CALL PM(#totalsum);
What you also can do is save all the sums in another session varialble
CREATE DEFINER=CURRENT_USER PROCEDURE `PM`()
MODIFIES SQL DATA
BEGIN
DECLARE nom_table VARCHAR(1000);
DECLARE site_table_uniq VARCHAR(50);
DECLARE x INT;
DECLARE nb_ligne INT;
DECLARE site_coord VARCHAR(1000);
SET nom_table = "";
SET site_table_uniq = "";
SET x = 1;
SET nb_ligne = (SELECT COUNT(*) FROM SIG_PM_THERMO);
# SIG PM THERMO is the table i want to fill with the number of rows
WHILE x <= nb_ligne DO
SET site_table_uniq = (SELECT pmthermo.Site_table FROM SIG_PM_THERMO pmthermo WHERE pmthermo.Id = x);
SET #site_coord = (SELECT pmthermo.Site_coord FROM SIG_PM_THERMO pmthermo WHERE pmthermo.Id = 1) ;
SET #nom_table = (SELECT pm.Nom_table FROM SIG_PM_THERMO pm WHERE pm.Site_table = site_table_uniq );
SET #sql = CONCAT('SELECT SUM(nb_therm) INTO #sumthermo FROM (SELECT COUNT(pmt.Temperature) AS nb_therm FROM ', #nom_table,' pmt WHERE pmt.Temperature !="-99" ) AS t ;');
SET #totalsum := #totalsum + #sumthermo ;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET x = x + 1;
END WHILE;
END
Now you only execute the procudre with
call PM();
and have also the values in #totalsum
The OUT variable is preferable, when you use python or other languages, that can run stored procedures
Is there a way to check if a table exists on database MySQL using Stored Procedure?
This is the SP, I expected when the table exists the variable value titem_id return 1 and when table not exists the variable value titem_id return 0.
Instead in all conditions (the table exists or not) the value is always zero...
Help me to do it.
I don't need number of records but check if exist table in database.
If table exists the return of value titem_id it's 1 else it's 0.
CREATE DEFINER=`root`#`%` PROCEDURE `SP`(tmonth int(2), tddlarea CHAR(100), OUT titem_id INT(11))
BEGIN
DECLARE 2tmonth int(2);
DECLARE 2tddlarea char(100);
DECLARE 2tyear int(4);
DECLARE 2titem_id int(11);
SET 2tmonth = tmonth;
SET 2tddlarea = tddlarea;
SET 2tyear = YEAR(CURDATE());
SET 2titem_id = 0;
SET #t = CONCAT('SELECT EXISTS(SELECT * FROM INFORMATION_SCHEMA.tables AS titem_id
WHERE table_schema = ''db''
AND table_name = ''t_contents_', 2tddlarea, '_', 2tmonth, '_', 2tyear, ''');');
PREPARE stmt FROM #t;
EXECUTE stmt;
DEALLOCATE PREPARE `stmt`;
SELECT #t;
IF #t = 1 THEN
SET titem_id := 1;
SET #s = -- EXECUTE SQL QUERY
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE `stmt`;
ELSE
SET titem_id := 0;
END IF;
END
UPDATE
CALL sys.table_exists('db', CONCAT('t_contents_', 2tddlarea, '_', 2tmonth, '_', 2tyear, ''), #exists);
SELECT #exists;
IF #exists > '' THEN
SET titem_id = 1;
SET #s = -- -- EXECUTE SQL QUERY
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
ELSE
SET titem_id = 0;
END IF;
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