Sql variable on select query - mysql

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

Related

Creating table incrementally using loops in a Stored Procedure

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();

Mysql stored procedure using cursor fetched variable in sql query

I have defined a following procedure.
create procedure deleteData()
begin
DECLARE no_tbls INT;
DECLARE tbl VARCHAR(64);
DECLARE tbls_cr CURSOR for SELECT DISTINCT table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='db';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_tbls=1;
OPEN tbls_cr;
SET no_tbls=0;
while no_tbls=0 do
fetch tbls_cr into tbl;
select tbl.updated_at from tbl limit 1;
end while;
close tbls_cr;
end
After running this procedure i am getting an error db.tbl doesn't exist.
So i was searching if there is a way to use a cursor fetched object in another query. The problem i am doing all this tedious stuff is that i would like to delete data from all tables of a db with a particular where clause.
Note: All tables has a column updated_at with date format.
(I am a newbie to MySQL stored procs).
You cannot have a variable in place of a table name in the from clause in a plain select statement, mysql will look for a table named tbl in the database.
You need to use string concatenation and prepared statements to dynamically create and execute sql statements:
mysql> USE test;
mysql> CREATE TABLE t1 (a INT NOT NULL);
mysql> INSERT INTO t1 VALUES (4), (8), (11), (32), (80);
mysql> SET #table = 't1';
mysql> SET #s = CONCAT('SELECT * FROM ',#table);
mysql> PREPARE stmt3 FROM #s;
mysql> EXECUTE stmt3;
mysql> DEALLOCATE PREPARE stmt3;
Prepared statements also work in stored procedures, the above example demonstrates how to create the sql statement by concatenating string literals with variables, prepare the statement, execute it, and then release the prepared statement from memory.
Using Prepare Statement you can fetch data dynamically
create procedure deleteData()
begin
DECLARE no_tbls INT;
DECLARE tbl VARCHAR(64);
DECLARE tbls_cr CURSOR for
SELECT DISTINCT table_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_schema='db';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_tbls=1;
OPEN tbls_cr;
start_loop : LOOP
fetch tbls_cr into tbl;
set #b = concat('select ', tbl, '.updated_at from ' , tbl, ' limit 1');
prepare stmt3 from #b;
execute stmt3;
DEALLOCATE PREPARE stmt3;
END LOOP start_loop;
close tbls_cr;
end

How do I select every row from a table based on a string containing the name of the table?

In MySQL, I have a number of procedures which are more or less identical - they all perform the same (or very similar) operations, but they perform it on different tables.
I'd like to reduce these to one procedure, parameterized by table name, if possible. For example, suppose I wanted to execute a generic select:
SELECT * FROM TableFor("TableName")
Is this (or anything similar) possible in MySQL? Is it possible in any SQL dialect?
Per Tomva's Answer
A full example:
DROP PROCEDURE IF EXISTS example;
CREATE PROCEDURE example(IN tablename VARCHAR(1000)) BEGIN
SET #statement = CONCAT('SELECT * FROM ', #tablename);
PREPARE statement FROM #statement;
EXECUTE statement;
DEALLOCATE PREPARE statement;
END;
CALL example('tablename');
You can do this with a prepared statement.
It will be something along the lines of
SET #stat = CONCAT('SELECT * FROM ', #tab');
PREPARE stat1 FROM #stat;
EXECUTE stat1;
DEALLOCATE PREPARE stat1;
Dynamic SQL does not work in a function, so make a Stored Procedure from this, and you will be able to provide the table parameter.
I am going to assume you know what a stored procedure is (I hope you do otherwise my answer will be useless)
First create a table object in your procedure
declare #tablenames table(name varchar)
insert into #MonthsSale (name) values ('firsttable')
insert into #MonthsSale (name) values ('secondtable')
...
You can add this little line to suppress the rows affected messages:
SET NOCOUNT ON
Then create a cursor for this table and a variable to save your table name
DECLARE #TABLENAME VARCHAR
DECLARE tables_cursor CURSOR FOR SELECT name FROM #tablenames
Then loop through cursor and execute your code for each table name
OPEN Tables_cursor
FETCH NEXT FROM Tables_cursor INTO #Tablename
WHILE ##FETCH_STATUS = 0
BEGIN
YOUR CODE USING THE #Tablename
END
CLOSE Tables_cursor
DEALLOCATE Tables_cursor

MySQL Stored Procedure that Calls a Table w/ dynamic Name

I have a stored procedure in MySQL that calls a function that inserts values into a table.
The insert statement is like
INSERT INTO Table1 SELECT * from Table2
Table2 has a variable name, depending on the date the procedure is called, like
table_201410 , if the procedure was called in October 2014. Soevery month, the procedure should make the select from another table.
I have read some answers about preparing and executing, however as I am new to MySQL/Programming. I am a bit lost.
You can use a prepared statement like this:
DELIMITER $$
DROP PROCEDURE copy_table $$
CREATE PROCEDURE copy_table ()
BEGIN
set #table_name = date_format(now(),'%Y%m'); -- getting year and month
-- concatenating
set #sql = concat('INSERT INTO Table1 SELECT * from table_',#table_name);
-- creating a prepared statement and executing
PREPARE insert_stmt FROM #sql;
EXECUTE insert_stmt;
DEALLOCATE PREPARE insert_stmt;
END$$
DELIMITER ;

How can I use the number of found rows assigned on a variable and use it in INSERT statement?

I want to get the number of results on my temporary table, so I created a query, something like this:
SELECT * FROM tmp_sales_negative; -- Selected all columns on my temporary table
SET #limit = (SELECT FOUND_ROWS()); -- Set a variable assignment named 'limit'
The above query works fine and I got the correct number of resulting rows, but when I use the variable name in this query:
INSERT INTO tmp_credit_memo_receivables(credit_memo_id, amount)
SELECT id, amount FROM credit ORDER BY id DESC LIMIT #limit;
It prompts a syntax error on #limit part. Am I doing it wrong?
Thanks!
You have to use dynamic sql for this. To use dynamic sql you have to do this in a stored procedure.
Create the procedure like this:
DELIMITER $$
CREATE PROCEDURE sp_limit()
BEGIN
SELECT SQL_CALC_FOUND_ROWS * FROM tmp_sales_negative;
SET #limit = (SELECT FOUND_ROWS());
SET #sql = 'INSERT INTO tmp_credit_memo_receivables(credit_memo_id, amount)
SELECT id, amount FROM credit ORDER BY id DESC LIMIT ?;';
PREPARE stmt FROM #sql;
EXECUTE stmt USING #limit;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
Then execute it with
CALL sp_limit();