Creating table incrementally using loops in a Stored Procedure - mysql

We have a large piece of complex SQL code that constantly falls over when run in HeidiSQL and MySQL WB. If we run the same code with smaller number of records it runs fine.
We are thinking that if we create a loop in an SP where the code is effectively split into 10 to 20 runs it may complete successfully. I think this may involve creating 10 to 20 tables which are union-ed into one table later on.
Tried running on smaller data sets, runs fine. Tried increasing the Server RAM and disk space. Tried adapting the code in many different ways.
I realise this may not be the ideal solution but have been asked to do it this way. If anyone could help me with the code, I would be grateful.
Below is code I built but doesn't work...
DELIMITER $$
DROP PROCEDURE IF EXISTS test_mysql_while_loop$$
CREATE PROCEDURE test_mysql_while_loop()
BEGIN
DECLARE x INT;
SET x = 100;
WHILE x <= 2000 DO
DROP TABLE if EXISTS tablex; /* want to end up with table100-table2000 */
CREATE TABLE tablex AS (
SELECT t1.*
FROM bigtables t1
WHERE urn BETWEEN x AND x+101); /* select records where the URN is between 100 and 201 in 1st instance , 200 and 301 in second etc*/
SET x=x+100;
END WHILE;
END$$
DELIMITER ;
CALL test_mysql_while_loop();
20 tables

Here's a simplified example of how to prepare and execute statements
DROP PROCEDURE IF EXISTS p;
delimiter $$
CREATE PROCEDURE p()
BEGIN
DECLARE x INT;
SET x = 100;
WHILE x <= 300 DO
set #sql= (select concat('DROP TABLE if EXISTS table',x));
select #sql;
prepare sqlstmt from #sql;
execute sqlstmt;
deallocate prepare sqlstmt;
set #sql = (select concat('CREATE TABLE table',x,' AS
SELECT t1.*
FROM users t1;'));
select #sql;
prepare sqlstmt from #sql;
execute sqlstmt;
deallocate prepare sqlstmt;
SET x=x+100;
END WHILE;
END$$
DELIMITER ;
CALL p();

Related

Have Stored Proc with Dynamic SQL that creates loads of results tabs

I have built an SP with Dynamic query code. Trouble is that every time it does something it sends something to a new results tab. Below is a cut down version of the code.
CREATE PROCEDURE p()
BEGIN
DECLARE x,z INT;
SET x = 0;
SET z = 0;
while z <= 9 DO
INSERT INTO loop_log (time, note) VALUES (NOW(), z);
/* Code block 1 - drop tables prior to creation*/
set #sql= (select concat('DROP TABLE if EXISTS table',z));
select #sql;
prepare sqlstmt from #sql;
execute sqlstmt;
deallocate prepare sqlstmt;
/* Code block 2 - create mini visit tables */
/* Loads of other code blocks */
SET z=z+1;
END WHILE;
END$$
DELIMITER ;
CALL p();
I really don't want any results tab from the code.
A stored procedure can generate multiple result sets, which will be shown in separate tabs, if you use a GUI client. A result set is send every time you execute a SELECT statement without storing it in a variable with
SET #var = (SELECT ...)
or
SELECT .. INTO #var ...
In your procedure the line
select #sql;
will be exected in every loop iteration and a result set will be send to the client. That might be good for debugging - But if you just want to execte the #sql statement, without showing it - Just remove that line.

How to create a create table statement in a loop in mysql

I want to create multiple tables with just one statement (query).
Loop
start
(
create table a
)
a =a +1
end loop
So say it has to create 100 tables labeled as TABLE1, TABLE2, ...
Try the following procedure.
DROP PROCEDURE IF EXISTS `createTableProcTest`;
delimiter //
CREATE PROCEDURE `createTableProcTest`()
BEGIN
DECLARE count INT Default 0;
simple_loop: LOOP
SET #a := count + 1;
SET #statement = CONCAT('Create table Table',#a,' ( name VARCHAR(70), age int );');
PREPARE stmt FROM #statement;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET count = count + 1;
IF count=100 THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
END//
In order to execute just do the following:
Call createTableProcTest();
By executing the above procedure 100 tables will be created having name table1,...,table100.
And the table structure would look like following:
N:B: Procedure execution might take several seconds. Don't be impatient.
You need give us more details but, I think is easier to call a stored procedure, inside the loop, to create the procedure.
You need to create a procedure to create the tables you need and call this procedure inside the loop.
Ex:
CREATE PROCEDURE SP_Create_Table(IN tableName VARCHAR(50)) BEGIN SET
#sql = CONCAT('CREATE TABLE ', tableName, '(column1 INT(11))');
PREPARE stmt FROM #sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END
Now, call the create table procedure inside the loop
DELIMITER // CREATE FUNCTION CalcIncome ( starting_value INT ) RETURNS
INT BEGIN
DECLARE income INT; SET income = 0; label1: WHILE income <=
50 DO
call SP_Create_Table(CONVERT(VARCHAR(50),starting_value)); END WHILE label1; RETURN income; END; // DELIMITER;

MySQL Procedure IN variable don't work properly

I'm learning Functions, Procedures and Triggers and I wanted to do a easy procedure that count the rows in a table from parameters.
create procedure countRows(IN v varchar(30))
SELECT COUNT(*) FROM v;
Can someone tell me why if I do:
call countRows('sometable');
call countRows(sometable); //I tried both
It just don't work
Sorry for that newbie question.
You need dynamic sql.
Solution for returning count of any table passed as a parameter to sp
DELIMITER $$
CREATE PROCEDURE `countRows`(IN v varchar(30))
BEGIN
SET #t1 =CONCAT("SELECT COUNT(*) FROM ",V);
PREPARE stmt3 FROM #t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END$$
DELIMITER ;
Execution
call countRows('sometable');
Update: Solution for returning "Table x contain n row(s)" for a table passed as a parameter to sp
DELIMITER $$
CREATE PROCEDURE `countRowsEx`(IN v VARCHAR(30))
BEGIN
-- SET #t1 =CONCAT("SELECT COUNT(*) FROM ",V);
SET #t1 =CONCAT('SET #totalRows=(SELECT COUNT(*) FROM ',v, ' );');
PREPARE stmt3 FROM #t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
SELECT CONCAT( 'Table ', v, ' contains ', #totalRows, ' row', IF(#totalRows>1, 's',''));
END$$
DELIMITER ;
Execution
call countRowsEx('sometable');
You can use information_schema for this.
for example to find rows count for table with name stored in variable v use this:
select table_rows from information_schema.tables where table_name = v;
Try this:
call countRows('v');

Changing Multiple DB Fields to Lower Case

With phpMyAdmin, I can use the following SQL to change all values in the table.field mytable.Site to lower case...
UPDATE my_table SET Site=LOWER(Site)
I have a zillion tables that have this same field, and I'd like to change all of them to lower case. Is there a SQL command that will do that - change EVERY field named Site in every table to lower case (preferably without having to list every table that has that field)?
Not EXACTLY what you want,but pretty close.Tested on my machine.
First create a procedure
delimiter //
CREATE PROCEDURE test(IN tbl CHAR(64))
BEGIN
SET #s = CONCAT('UPDATE ',tbl,' SET Site=LOWER(Site)' );
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
//
delimiter ;
And for finding tables with a certain column name:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('Site')
AND TABLE_SCHEMA='YourDB';
For calling the procedure
CALL test('tableName')

Sql variable on select query

hey lets say we have 3 tables tbl1,tbl2,tbl3 and using the below query you can view the data
select * from tbl1
select * from tbl2
select * from tbl3
my question is that can you eliminate repetition by using variables? like for example
DECLARE #x as varchar(60)
set #x = tbl1
set #x = tbl2
set #x = tbl3
select * from #x
Go
I hate retyping the exact query does anyone know a way to make the query work I think it would save me loads of time. thanks
Why not create a stored procedure for that?
Example:
DELIMITER $$
DROP PROCEDURE IF EXISTS `selectAllTables`$$
CREATE PROCEDURE `selectAllTables`()
BEGIN
SELECT * from tbl1;
SELECT * from tbl2;
SELECT * from tbl3;
END$$
DELIMITER ;
Usage:
CALL `selectAllTables`();
If you meant Dynamic SQL (SQL Server) type of support in MySQL, you may achieve this using prepare statement in stored procedure
First create a stored procedure with a parameter to take table name in string:
DELIMITER ///
CREATE PROCEDURE SelectAllRecords(__TABLE__NAME varchar(255))
BEGIN
SET #sql = CONCAT('SELECT * FROM ', __TABLE__NAME);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END///
DELIMITER ;
Next, you may CALL the stored procedure sending in the table name:
call SelectAllRecords('table1')
call SelectAllRecords('table2')
call SelectAllRecords('table3')
If i got your Question right then the below Query will work for you.
DECLARE #x as table
set #x = select * from tbl3
select * from #x
Go