Key commands for creating temporary tables - mysql

I am creating temporary tables in stored procedures. Wanted to know what commands to include in procedure to avoid conflicts?
i usually use below syntax
CREATE TEMPORARY TABLE IF NOT EXISTS temp_shipmentcount
and use
drop command at end.
should i add drop command at beginning of procedure also?

Temporary tables are connection scoped. They only exist until the connection is closed.
As per documentation on Temporary tables
You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only to the current connection, and is dropped automatically when the connection is closed. This means that two different connections can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name...
If a connection is not closed but shared among users, then you have to drop it and re-create. But dropping a database object using a shared connection will result issues.
It would be a better option to use temporary tables with runtime generated names within a stored procedure. This is safe on using shared connection objects too.
Exampe:
set #temp_table_name := concat( 'temp_table_', ( CURRENT_TIMESTAMP + 0 ) );
set #sql := concat( 'create temporary table ', #temp_table_name );
set #select_stmt := concat( 'select this', blah, blah );
set #sql := concat( #sql, ' as ' , #select_stmt );
prepare stmt from #sql;
execute stmt;
drop prepare stmt;
-- perform opearations on temp table
--
-- in between here
--
-- and then drop it before leaving
set #drop_temp := concat( 'drop temporary table ', #temp_table_name );
prepare stmt from #drop_temp;
execute stmt;
drop prepare stmt;

Related

MySQL Procedure to CREATE multiple tables is not working (WHILE loop dynamic SQL)

I have added a stored procedure to create multiple tables in dynamic SQL using WHILE loop in MySQL Workbench. The query creates last table only, instead of all. I have checked with drop table to delete the if table exists. But it still show already exists. Here is the query.
CREATE DEFINER=`root`#`localhost` PROCEDURE `weeklyLooper`(IN weeklycount INT)
BEGIN
SET #count = 0;
SET #weeklylooper = weeklycount;
SET #dumpclear = CONCAT('week' , #weeklylooper);
WHILE #count <= #weeklylooper DO
set #count = #count+1;
SET #weeklyname = CONCAT('week' , #count);
SET #weekly = CONCAT('total_' , #weeklyname, '_deposits');
SET #dropquery = CONCAT('DROP TABLE IF EXISTS `', #weeklyname, '`');
PREPARE droptablequery FROM #dropquery;
EXECUTE droptablequery;
DEALLOCATE PREPARE droptablequery;
SET #selectquery = CONCAT('CREATE temporary TABLE ', #weeklyname ,' AS SELECT sum(deposits) As ', #weekly,' FROM base0');
PREPARE selecttablequery FROM #selectquery;
EXECUTE selecttablequery;
DEALLOCATE PREPARE selecttablequery;
END WHILE;
END
Please help me to complete this.
You are creating temporary tables - temporary tables only exist for the extent of the session - since every exec is in a unique session AND DIFFERS from the session you are running the procedure in the temporary tables are never available to the session in which you are running the procedure...
or as the manual says 'You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only within the current session, and is dropped automatically when the session is closed.' https://dev.mysql.com/doc/refman/8.0/en/create-temporary-table.html
Consider creating permanent tables and deleting them when you are done.

TRUNCATE all tables matching name pattern

This is the sql i'm using based from this answer:
SET #pattern = '%_movielist';
SELECT concat('TRUNCATE TABLE ', GROUP_CONCAT(concat(TABLE_NAME)), ';')
INTO #truncatelike FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE #pattern;
SELECT #truncatelike;
PREPARE stmt FROM #truncatelike;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
but I get this error Access denied for user 'root'#'%' to database 'information_schema'.
What am I doing wrong? It seems to work for other users
You trying to execute this statement on "information_schema" database. Read more about this database [https://dev.mysql.com/doc/refman/5.7/en/information-schema.html]
You should not be running statements on the information_schema database (unless you REALLY know what you're doing). The database serves as a "meta" repository that dictates how the server operates. Chances are that you have no need to touch it and you'll likely brick your server if you do.
This is already answered here. [#1044 - Access denied for user 'root'#'localhost' to database 'information_schema'
Restriction to above: This query will work only if the no of table returned by the statement is 1 for more than 1 tables, you will require to use it in iteration.
To make this work for all the table matching the pattern we would require to use stored procedure.
Please change the Procedure name
CREATE PROCEDURE `new_procedure`()
BEGIN
-- Pattern to Match
SET #pattern = '%_movielist';
-- Temporary Table to Store the Result of The Select Statement
CREATE TEMPORARY TABLE IF NOT EXISTS Table_ToBeTruncated
(
Id int NOT NULL AUTO_INCREMENT,TableName varchar(100),
PRIMARY KEY (id)
);
-- Insert all the TableName to be Truncated
insert Table_ToBeTruncated(TableName)
SELECT distinct concat('TRUNCATE TABLE `', TABLE_NAME, '`;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE #pattern and TABLE_SCHEMA = 'movielist';
-- Declare a variable to count the no of records to be truncated.
SET #count=(Select count(*)from Table_ToBeTruncated);
-- Iterate the list
WHILE #count> 0 DO
-- Pick One table from the Temporary Table List;
SELECT TableName into #truncatelike from Table_ToBeTruncated where ID= #count;
-- Prepare the statement
PREPARE stmt FROM #truncatelike;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Decrease the counter.
set #count = #count- 1;
END WHILE;
drop TEMPORARY TABLE IF EXISTS Table_ToBeTruncated ;
END

How to convert an SQL select query into a formatted HTML table within a MySQL function

I'm looking for a way to generate valid HTML code within MySQL (without PHP) by converting any query output into an HTML table.
Here's my progress so far and evidently, I'm stuck. I hope I can get some help, thanks.
1. "dynSQL" - A procedure to take any Select query and create a named table out of it
Since MySQL doesn't allow dynamic queries in functions, I'm calling a procedure that creates a named table, tmp. I can't use a temporary table because info about temporary tables is not available in information_schema (in mysql 5.6)
CREATE DEFINER=`root`#`%` PROCEDURE `dynSQL`(SQL_QUERY TEXT)
BEGIN
set #SQLQ := 'Drop table if exists tmp;';
PREPARE stmt from #SQLQ;
Execute stmt;
SET #SQLQ := concat('create table tmp as ',SQL_QUERY);
PREPARE stmt from #SQLQ;
Execute stmt;
-- I'm adding a auto increment ID column to be able to loop through the rows later
SET #SQLQ := "ALTER TABLE tmp add column CustColHTML_ID INT NOT NULL AUTO_INCREMENT FIRST, ADD primary KEY Id(CustColHTML_ID)";
PREPARE stmt from #SQLQ;
Execute stmt;
DEALLOCATE PREPARE stmt;
END
2. "MakeHTML" - Function to read from the table tmp and return a formatted HTML table
CREATE DEFINER=`root`#`%` FUNCTION `MakeHTML`() RETURNS text CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE HTML text default "<TABLE><TR>";
DECLARE rowCount int default 0;
DECLARE i int default 0;
select concat('<TR>',group_concat('<TD>',column_name,'</TD>' separator ''),'</TR>') into html from information_Schema.`columns` where table_name='tmp';
Select max(CustColHTML_ID) into rowCount from `tmp`; -- Set the row counter
WHILE i<=rowCount DO
-- What do I do here? How do I loop through the columns of table tmp?
set i:=i+1;
END WHILE;
RETURN HTML;
END
As you can see, I'm stuck at looping through the unknown and dynamic columns of table tmp. I read about how a cursor can be used here, but all the examples I saw make use of known columns and assign those into named variables. However, since the query itself is dynamic, I wouldn't know the names of the columns.
I'd really appreciate your time and assistance, thanks!
p.s. I've posted this as a new question because my earlier question was marked as closed as being too broad. I subsequently edited my question but it was still showing as Closed. I've therefore deleted the older question and replaced it with this one.
With a sample table as such:
CREATE TABLE tmp (ID INT, Col1 INT, Col2 INT);
The SQL you would need to generate your HTML is:
SELECT CONCAT('<table>', GROUP_CONCAT(CONCAT('<tr><td>',ID,'</td><td>',Col1,'</td><td>',Col2,'</td><tr>')), '</table>')
FROM tmp;
You can generate this using the INFORMATION_SCHEMA:
SELECT CONCAT
(
'SELECT CONCAT(''<table>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp';
It is then just a case of executing this:
SET #SQL = (
SELECT CONCAT
(
'SELECT CONCAT(''<table>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Example on SQL Fiddle
ADDENDEUM
Forgot to include table headers:
SET #SQL = (
SELECT CONCAT
(
'SELECT CONCAT(''<table><tr>'',',
GROUP_CONCAT(CONCAT('''<th>'',''', COLUMN_NAME, ''',''</th>''')),
', ''</tr>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Example on SQL Fiddle

Using Dynamic MySQL to create a new table

I want to change this query:
CREATE TABLE diablo.diablo_sales2 LIKE diablo.diablo_sales;
to a dynamic one like this:
set #old = 'diablo_sales';
set #new = 'diablo_sales2 ';
set #schema = 'diablo';
set #query = 'create table #schema.#new like #schema.#old';
Is this even possible in MySQL? How can I execute #query?
EDIT: below is the whole query I'm trying to make dynamic
-- create same table structure - blank table
CREATE TABLE diablo.diablo_sales2 LIKE diablo.diablo_sales;
-- add the new column(s)
ALTER TABLE diablo.diablo_sales2
add column new_column decimal(10);
-- insert the old data into new table - new column will remain blank
INSERT INTO diablo.diablo_sales2
(
column1,
column2
)
SELECT * FROM diablo.diablo_sales;
-- rename the new table to its original name. Drop the old table.
RENAME table diablo_sales TO `old`, diablo_sales2 TO diablo_sales;
DROP TABLE old;
You can use the SQL Syntax for Prepared Statements:
SET #sql := CONCAT('
CREATE TABLE `',REPLACE(#schema,'`','``'),'`.`',REPLACE(#new,'`','``'),'`
LIKE `',REPLACE(#schema,'`','``'),'`.`',REPLACE(#old,'`','``'),'`
');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I have taken the liberty of quoting the identifiers and calling REPLACE() to escape any quotes contained therein, in order to protect against SQL injection.

How to create temporary table and generate different name in mysql procedure?

I want to create temp tables which have different table names.
The stored procedure takes no input arguments, create a temp table and return
a table name of the table as T_1, T_2, T_3....
How can I implement this in mysql stored procedure?
You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only to the current session, and is dropped automatically when the session is closed. This means that two different sessions can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name. (The existing table is hidden until the temporary table is dropped.) To create temporary tables, you must have the CREATE TEMPORARY TABLES privilege.
Following procedure should help you. But this kind of sequence generation will work in current connection session only. But I hope it is OK as you are expecting it on temporary tables.
delimiter //
drop procedure if exists set_new_temp_table //
create procedure set_new_temp_table()
begin
if( #temp_table_seq_num is null ) then
set #temp_table_seq_num := 1;
end if;
set #temp_table_name := Concat( 'T_', #temp_table_seq_num );
set #sql := concat( 'create temporary table if not exists '
, #temp_table_name
, '( col1 int, col2 varchar(10) )'
);
prepare stmt from #sql;
execute stmt;
drop prepare stmt;
set #temp_table_seq_num := ( cast( #temp_table_seq_num as decimal ) + 1 );
set #sql := null;
end;
//
delimiter ;
select #temp_table_name; -- should return a NULL before first ever call to SP
call set_new_temp_table(); select #temp_table_name;
Demo # MySQL 5.5.32 Fiddle
This is full example
SELECT UUID() INTO #RandomName;
SET #TempTableNameWithSpecialCharectors := CONCAT('TEMP', #RandomName);
SET #TempTableName := REPLACE(#TempTableNameWithSpecialCharectors, '-', '');
SET #tempTable := CONCAT('CREATE TEMPORARY TABLE IF NOT EXISTS ', #TempTableName, ' (InteractionRequestId bigint(20), SendCount int)');
-- SELECT #tempTable;
PREPARE createStmt FROM #tempTable;
EXECUTE createStmt;
DROP PREPARE createStmt;
SET #enqueueDate := '2017-05-28';
SET #insertIntoTable := CONCAT('
INSERT INTO ', #TempTableName, '(InteractionRequestId, SendCount) SELECT InReq.Id, COUNT(*) AS SendCount FROM InteractionRequests AS InReq INNER JOIN InteractionResponses InRes ON InReq.Id = InRes.InteractionRequestId
WHERE InReq.EnqueuedRequest > "', #enqueueDate,
'" GROUP BY InReq.Id');
SELECT #insertIntoTable;
PREPARE insertStmt FROM #insertIntoTable;
EXECUTE insertStmt;
DROP PREPARE insertStmt;
SET #SelctResult := CONCAT('SELECT * FROM ', #TempTableName);
PREPARE selectStmt FROM #SelctResult;
EXECUTE selectStmt;
DROP PREPARE selectStmt;