i'm trying to slice a long double Column by Varied size , and insert it with cursor to new table that has this size of columns amount.
the trouble is the cursor isn't responding?
I tried to activate the cursor (Externally) manually And managed to.
So I have the impression cursor does not work within procedure?!
Here's the code:
The outer procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `slice_arrays`(IN `size` INT)
DETERMINISTIC
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE h INT DEFAULT 0;
DECLARE q_creat text DEFAULT "";
DECLARE cell text DEFAULT "cell";
DECLARE cell_type text DEFAULT "double";
DECLARE new_table_name text DEFAULT "";
set new_table_name=CONCAT("table_1440_slice_by_",size);
SELECT COUNT(*) FROM eurusd_1440_minute_timeframe_chart_bars INTO n;
SET #q_creat =CONCAT("CREATE TABLE IF NOT EXISTS ",new_table_name," (");
WHILE h < size DO
SET #q_creat = CONCAT(#q_creat,cell,h," ",cell_type);
set #h_pluse_1=h+1;
if #h_pluse_1 = size THEN
SET #q_creat= CONCAT(#q_creat,")");
else
SET #q_creat= CONCAT(#q_creat,",");
end if;
set h=h+1;
END WHILE;
PREPARE stmt1 FROM #q_creat;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
TRUNCATE TABLE new_table_name;
set h=0;
set #temp_cuonter=size;
WHILE #temp_cuonter <= n DO
drop table IF EXISTS temp_table;
create table temp_table as (SELECT * FROM table_1440_test3 LIMIT h , size);
CALL insert_into_selected_table_from_temp_table(new_table_name);
set h=h+1;
set #temp_cuonter =#temp_cuonter+1;
TRUNCATE TABLE tamp_table;
end while;
End
The nested procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `insert_into_selected_table_from_temp_table`(IN `table_name` TEXT)
DETERMINISTIC
begin
set #insert_q= CONCAT("INSERT INTO ",table_name," VALUES(");
set #insert_q= CONCAT(#insert_q,get_temp_table(),")");
PREPARE stmt2 FROM #insert_q;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
end
thanks!
Related
I am trying to create a Procedure during the creation of a database, the mysql query is as follows:
CREATE DATABASE database_Sensor1;
USE database_Sensor1;
CREATE TABLE Persons(id int NOT NULL);
DELIMITER //
CREATE PROCEDURE MYLOOP() IF database_Sensor1 EXISTS
BEGIN
DECLARE i int;
DECLARE str varchar(255);
SET i = 0;
WHILE i < 32 DO
SET str = CONCAT('col_',i);
SET #sql = CONCAT('ALTER TABLE persons ADD ',str,' float;');
SET i = i + 1;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END WHILE;
END
DELIMITER ;
CALL MYLOOP();
But I get this error:
#1305 - PROCEDURE database_sensor1.MYLOOP does not exist
I am trying to use the Procedure to Loop the table creation by quickly altering the table to add 32 columns in so that I can run another .php to add in the values.
CREATE DATABASE database_Sensor1;
USE database_Sensor1;
CREATE TABLE database_Sensor1.Persons(id int NOT NULL);
DELIMITER //
CREATE PROCEDURE database_Sensor1.MYLOOP()
BEGIN
DECLARE i int;
DECLARE str varchar(255);
SET i = 0;
WHILE i < 32 DO
SET str = CONCAT('col_',i);
SET #sql = CONCAT('ALTER TABLE database_Sensor1.persons ADD ',str,' float;');
SET i = i + 1;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END WHILE;
END
//
DELIMITER ;
CALL MYLOOP();
Editions:
IF database_name EXISTS construction not exists. Removed. See edition 3.
Procedure creation code is not finalized with delimiter. Added.
The database in which the procedure must be created is not specified explicitly. Added. If the database not exists then the error will be generated. The same with the table name.
I am mass assigning new id numbers to things in the DB to make room for some stuff at the beginning of each table. I created a procedure that works, but when I try adding input parameters to allow scripting, it can't find the table
delimiter |
CREATE PROCEDURE changeID
( IN in_table_name varchar(64))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE a,b INT DEFAULT 800000;
DECLARE cur1 CURSOR FOR SELECT id FROM in_table_name ORDER BY id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO b;
IF done THEN
LEAVE read_loop;
END IF;
UPDATE in_table_name SET id = a + 1 where id = b;
SET a = a+1;
END LOOP;
CLOSE cur1;
END;
|
delimiter ;
When I run this using call changeID('users'), I get the error:
[Err] 1146 - Table 'databaseName.in_table_name' doesn't exist
I was hoping to loop through using a simple list of commands like this so it could run unattended instead of manually changing the in_table_name between each execution:
call changeID('users');
call changeID('appointments');
call changeID('groups');
You can't dynamically pass a table name in a query, however, you can concatenate a string and then execute it as a statement. You of course want to be careful and ensure that this data has been sanitized etc. I wasn't able to test this, but something to this effect should get you going.
...
END IF;
SET #Query = CONCAT('UPDATE ',in_table_name,' SET `id` = ',a+1,' WHERE `id`=',b);
PREPARE stmt FROM #Query;
EXECUTE stmt;
...
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
KChason got me started in the right direction, but I had to take it a little further to get the first part working from tips here: https://forums.mysql.com/read.php?98,138495,138908#msg-138908.
DROP PROCEDURE
IF EXISTS `workingversion`;
delimiter |
CREATE PROCEDURE `workingversion` (IN tableName VARCHAR(100))
BEGIN
DECLARE done INT DEFAULT 0 ;
DECLARE a,
b INT DEFAULT 800000 ;
DROP VIEW IF EXISTS v1;
SET #stmt_text = CONCAT("CREATE VIEW v1 AS SELECT id FROM ", tableName, " ORDER BY id") ;
PREPARE stmt
FROM
#stmt_text ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
BEGIN
DECLARE cur1 CURSOR FOR SELECT * FROM v1 ;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000'
SET done = 1 ; OPEN cur1 ;
REPEAT
FETCH cur1 INTO b ;
IF NOT done THEN
SET #Query = CONCAT('UPDATE ',tableName,' SET `id` = ',a+1,' WHERE `id`=',b);
PREPARE stmt FROM #Query;
EXECUTE stmt;
SET a = a+1;
END
IF ; UNTIL done
END
REPEAT
; CLOSE cur1 ;
END ;
END
I have 2 schemas with exactly the same tables schema_oltp and schema_olap. I want to delete from selected tables in schema_oltp only the data which already exists in schema_olap. The tables I want to delete from are listed in a table called archived_to_delete. For each of the tables listed in archived_to_delete, I need to delete the data in batches of 100 000. This is what I have so far. It only deletes 100 000 in each table and stops. I want it to continue until there is no data in schema_oltp which also exists in schema_olap:
DELIMITER $$
CREATE DEFINER=`root`#`%` PROCEDURE `schema_oltp`.`schemaDeletes`(IN from_schema VARCHAR(100), IN to_schema VARCHAR(100))
BEGIN
DECLARE v_tname varchar(100);
DECLARE v_pkey varchar(455);
DECLARE v_upfield varchar(455);
DECLARE done INT DEFAULT 0;
DECLARE v_limit INT DEFAULT 100000;
DECLARE v_deleted INT;
DECLARE table_cursor CURSOR FOR SELECT a.table_name, a.column_name
FROM INFORMATION_SCHEMA.COLUMNS a
INNER JOIN archived_to_delete b
ON a.table_name = b.table_name
WHERE TABLE_SCHEMA = 'schema_oltp'
AND COLUMN_KEY='PRI'
ORDER BY b.archived_to_delete_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN table_cursor;
REPEAT
FETCH table_cursor INTO v_tname, v_pkey;
IF NOT done THEN
SET v_deleted=0;
SET #sql = CONCAT('DELETE FROM ',from_schema,'.', v_tname, ' WHERE ',v_pkey,' IN (SELECT ', v_pkey, ' FROM ',to_schema,'.', v_tname, ') limit ',v_limit,';');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET v_deleted=v_deleted+1;
IF v_deleted = v_limit THEN
commit;
SET v_deleted=0;
END IF;
SELECT CONCAT('Deleting...',v_tname);
END IF;
UNTIL done END REPEAT;
CLOSE table_cursor;
END$$
DELIMITER ;
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
I have a problem with curosr exactly with query : SELECT Crc32 FROM tableName. I want read all rows from Crc32 column and based on the first four characters find a table that has the same name as the four digits
Error:
0 12:58:57 call ShowNewUserComments("User66") Error Code: 1146. Table 'comments.tableName' doesn't exist
Call Procedure:
call ShowNewUserComments("User66");
Code
DELIMITER $$
DROP PROCEDURE IF EXiSTS ShowNewUserComments $$
CREATE PROCEDURE `ShowNewUserComments`(tableName varchar(255)/*, Date TIMESTAMP*/)
BEGIN
DECLARE recordNotFound INTEGER DEFAULT 0;
DECLARE oneRow VARCHAR(10) DEFAULT "";
DECLARE getCrc32,i int (11);
DECLARE myCursor CURSOR FOR SELECT Crc32 FROM tableName;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET recordNotFound = 1;
OPEN myCursor;
set i = 0;
allRows: LOOP
FETCH myCursor INTO oneRow;
set i = i + 1;
IF recordNotFound THEN
LEAVE allRows;
END IF;
END LOOP allRows;
CLOSE myCursor;
END
You can't directly substitute table name from variable into query in MySQL, for that you need to use dynamic sql using PREPARE like this:
DELIMITER $$
DROP PROCEDURE IF EXiSTS ShowNewUserComments $$
CREATE PROCEDURE `ShowNewUserComments`(tableName varchar(255)/*, Date TIMESTAMP*/)
BEGIN
DECLARE recordNotFound INTEGER DEFAULT 0;
DECLARE oneRow VARCHAR(10) DEFAULT "";
DECLARE getCrc32,i int (11);
DECLARE myCursor CURSOR FOR SELECT Crc32 FROM temp_table;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET recordNotFound = 1;
DROP TEMPORARY TABLE IF EXISTS temp_table;
SET #query1 = CONCAT('CREATE TEMPORARY TABLE temp_table AS
SELECT Crc32
FROM ',tableName,' ');
PREPARE stmt FROM #query1; EXECUTE stmt; DEALLOCATE PREPARE stmt;
OPEN myCursor;
set i = 0;
allRows: LOOP
FETCH myCursor INTO oneRow;
set i = i + 1;
IF recordNotFound THEN
LEAVE allRows;
END IF;
END LOOP allRows;
CLOSE myCursor;
DROP TEMPORARY TABLE IF EXISTS temp_table;
END