How to create a table in mysql with a random name? - mysql

I have a procedure that update a table. However, I need to back up the table each time prior updating it. So the only way I can backup the table via procedure is by create a table and inserting all the information from one table to another.
So What I need to do is create a table name with a random value to distinguish the different tables. The ideal solution will be "New_Table_Name_TIMESTAMP" so append timestamp to a string.
My Question is how to create a table with a timestamp added to it's name
New_table_name_201412301044
I have tried the following
DECLARE new_table varchar(100) DEFAULT '';
SET new_table = CONCAT('WORKFLOW_BU_', client_id_to_update, '_', unix_timestamp() );
CREATE TABLE data_import.new_table LIKE development.inventory_engine;
INSERT INTO data_import.new_table
SELECT * FROM development.inventory_engine;
but it create a table name called "new_table" and not the variable
Thanks

You're going to have to use so-called dynamic SQL, also known as "server side prepared statements" to do this. Ordinary SQL prohibits the use of variables for the names of tables or columns.
See here.
http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html

sounds like a bad idea but you could do it with PREPARE statement FROM #sql and EXECUTE statement like this sqlFiddle
sample table
CREATE table yourTable(id int auto_increment primary key,value varchar(50));
INSERT into yourtable(value) values ('test1'),('test2'),('test3'),('test4');
create a table with a time_stamp ending (in the example I am only recording down to the HOUR, you can add _%i_%s to the formatting if you want it down to the seconds.
SET #TimeStamp = DATE_FORMAT(NOW(),'%Y_%m_%d_%H');
SET #sql = CONCAT('CREATE table yourTable',#TimeStamp,'(id int auto_increment primary key,value varchar(50))');
PREPARE statement FROM #sql;
EXECUTE statement;
SET #sql = CONCAT('INSERT INTO yourTable',#TimeStamp,'(id,value) SELECT id,value FROM yourTable');
PREPARE statement FROM #sql;
EXECUTE statement;

Related

Search Specific Range of Tables mySQL

I have a question that is plaguing me. I have a mysql database that is being used for historical data. Basically every year the system writes a new table in the database housing the time data.
so it is like this:
tables:
year_2017
year_2018
year_2019
and in each table there is data.
What I would like to do is build a query that will search through these specific tables.
Now there are other tables in there I don't want to search through. I only want the year_* tables.
Basically I would want SELECT * FROM year_*
I know you could do SELECT * FROM year_2017, year_2018, year_2019 but the problem is that every year there is going to be a new table so I would have to edit the query every year and I don't want to do that.
Any help would be great.
From the information_schema.tables, find the names of the tables that contain the year_ and then place the table names in a temporary table. Then fetch each table with a data loop.
CREATE PROCEDURE myproc()
BEGIN
CREATE TEMPORARY TABLE temp(
tablename varchar(100)
);
INSERT INTO temp
SELECT t.TABLE_NAME
FROM information_schema.tables t
WHERE t.TABLE_NAME LIKE '%year_%';
WHILE (Select Count(*) From temp) > 0 DO
SET #tablename= (Select tablename From temp limit 1);
SET #sql= concat("select * from ", #tablename);
prepare exec from #sql;
execute exec;
Delete From temp Where tablename=#tablename;
END WHILE;
END;
CALL myproc();
demo in db<>fiddle
You can use a variable to store the table name. But you'd need to come up with an automation to fill the table name variables.
mysql prepared statements
/* MYSQL */
SET #table = 't1';
SET #s = CONCAT('SELECT * FROM ', #table);
PREPARE stmt3 FROM #s;
EXECUTE stmt3;

Is it possible to have a MySQL table comment defined before its create statement?

In order to document SQL code in a more linear fashion, I wanted to make appear the description of a table that is going to be created before the creation statement. So my first idea was to put that in a user-defined variable with which I could fill the comment instruction, but it seems to be unsupported (at least in the 5.6 version I have to deal with):
set #description = 'The following table is a useless dummy test.';
drop table if exists `test`;
create table `test` (dummy int) comment #test; -- syntax error
show table status where name='test';
Is there an other way to achieve the initial goal? Of course it's always possible to use -- SQL comments before the creation statement, but then it wouldn't appear in the recorded database structure, or at the price of a awful duplication.
We might be able to do this using dynamic SQL:
SET #description = 'The following table is a useless dummy test.';
SET #sql = CONCAT('CREATE TABLE test (dummy int) COMMENT=''', #description, '''');
PREPARE stmt FROM #sql;
EXECUTE stmt;
Note that each prepared statement is precisely just that; a single statement. So, to do this from the command line, you might need 3 statements to cover the full logic you want to run.
Although it doesn't match the question, here is a solution to its underlying problem: having the description of a table directly next to it's creation statement.
The MySQL syntax require to put the comment attached to the table at the end, but if the table have many fields, each declared on one or several lines, then the table comment can quickly be sent of sight of its declaration start.
Now, one can easily create a table with it's comment as sole attached statement, then alter it to include fields it should contains.
CREATE TALBE `test` COMMENT 'Informative description';
ALTER TABLE test
ADD id
INT UNSIGNED NOT NULL AUTO_INCREMENT
COMMENT 'Description of the id field',
ADD data
BLOB
COMMENT 'Description of the data field',
;

Copying Tables Without Data in MySQL Retaining Auto Increment

I have ran into trouble when copying my MySQL Tables to a new one, excluding the data, using the query:
CREATE TABLE foo SELECT * FROM bar WHERE 1=0.
The tables are copied, the structure and column names are correctly inserted. But there is a problem with the auto_increment fields and the primary key fields as they are not inserted as they were on the original table. (The fields are not PKs and AI anymore) I am using MySQL 5.5 and PMA 3.5.8.2
I hope someone can help me out.
Thank you SO.
You will probably have to run 2 queries.
CREATE TABLE foo LIKE bar;
ALTER TABLE foo AUTO_INCREMENT = (SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'DatabaseName' AND TABLE_NAME = 'bar');
You would have to replace DatabaseName with the name of your database. This is untested, but I think it will give you what you are looking for.
So I tried testing the above query and the ALTER TABLE statement seems to fail due to the select. There might be a better way, but the way that worked for me was to set the auto increment value to a variable and then prepare the statement and execute it.
For example you would go ahead and create your table first:
CREATE TABLE foo LIKE bar;
Then set your ALTER TABLE statement into a variable
SET #ai = CONCAT("ALTER TABLE foo AUTO_INCREMENT =", (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'databasename' AND TABLE_NAME = 'bar'));
Finally, you would prepare and execute the statement.
PREPARE query FROM #ai;
EXECUTE query;
DEALLOCATE PREPARE query;
Other than your columns, the table structure: indexes, primary keys, triggers, etc. are not copied by this kind of statement. You either need to run a bunch of alter table statements to add your structure or you need to create the table with all the surrounding structure first, then load it with your select.

How to create dynamic table in mySql

I want to know how to create dynamic table in mySql . I have used dynamic table in Sqlserver 2008 but i am new to mySql . Is it possible ?
Eg: In Sql server i have created Dynamic Customer Table.
DECLARE #tblCustomer as table(
[ ] bit
,Sl# int
,custID int
,CustCode varchar(max)
,Customer nvarchar(max)
,Authorized bit
,RCount int)
SELECT * FROM #tblCustomer
Please Help
#sqlstmt = 'whatever sql';
Prepare st from #sqlstmt;
Execute #st;
Deallocate prepare #st;
Place the CREATE TABLE statement in #sqlstmt and you are good to go !
The table is a real one. You would have to drop the table afterwards.
Pretty easy to do:
CREATE TABLE AS
SELECT * FROM tblCustomer
It will take the existing field types from the schema where possible..

Duplicating a MySQL table, indices, and data

How do I copy or clone or duplicate the data, structure,
and indices of a MySQL table to a new one?
This is what I've found so far.
This will copy the data and the structure,
but not the indices:
create table {new_table} select * from {old_table};
This will copy the structure and indices,
but not the data:
create table {new_table} like {old_table};
To copy with indexes and triggers do these 2 queries:
CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table SELECT * FROM old_table;
To copy just structure and data use this one:
CREATE TABLE new_table AS SELECT * FROM old_table;
I've asked this before:
Copy a MySQL table including indexes
Apart from the solution above, you can use AS to make it in one line.
CREATE TABLE tbl_new AS SELECT * FROM tbl_old;
MySQL way:
CREATE TABLE recipes_new LIKE production.recipes;
INSERT recipes_new SELECT * FROM production.recipes;
Go to phpMyAdmin and select your original table then select "Operations" tab in the "Copy table to (database.table)" area. Select the database where you want to copy and add a name for your new table.
I found the same situation and the approach which I took was as follows:
Execute SHOW CREATE TABLE <table name to clone> : This will give you the Create Table syntax for the table which you want to clone
Run the CREATE TABLE query by changing the table name to clone the table.
This will create exact replica of the table which you want to clone along with indexes. The only thing which you then need is to rename the indexes (if required).
The better way to duplicate a table is using only DDL statement. In this way, independently from the number of records in the table, you can perform the duplication instantly.
My purpose is:
DROP TABLE IF EXISTS table_name_OLD;
CREATE TABLE table_name_NEW LIKE table_name;
RENAME TABLE table_name TO table_name_OLD;
RENAME TABLE table_name _NEW TO table_name;
This avoids the INSERT AS SELECT statement that, in case of table with a lot of records can take time to be executed.
I suggest also to create a PLSQL procedure as the following example:
DELIMITER //
CREATE PROCEDURE backup_table(tbl_name varchar(255))
BEGIN
-- DROP TABLE IF EXISTS GLS_DEVICES_OLD;
SET #query = concat('DROP TABLE IF EXISTS ',tbl_name,'_OLD');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- CREATE TABLE GLS_DEVICES_NEW LIKE GLS_DEVICES;
SET #query = concat('CREATE TABLE ',tbl_name,'_NEW LIKE ',tbl_name);
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- RENAME TABLE GLS_DEVICES TO GLS_DEVICES_OLD;
SET #query = concat('RENAME TABLE ',tbl_name,' TO ',tbl_name,'_OLD');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- RENAME TABLE GLS_DEVICES_NEW TO GLS_DEVICES;
SET #query = concat('RENAME TABLE ',tbl_name,'_NEW TO ',tbl_name);
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END//
DELIMITER ;
Have a nice day!
Alex
To duplicate a table and its structure without data from a different a database use this. On the new database sql type
CREATE TABLE currentdatabase.tablename LIKE olddatabase.tablename
Worths to mention the importance of checking if the table already exists before
trying to duplicate it:
CREATE TABLE IF NOT EXISTS new_table LIKE old_table;
INSERT new_table
SELECT * FROM old_table;
As was said by the previous answers this will copy structure, data and
all the dependent objects of the table.
See MySql Tutorial:
Expanding on this answer one could use a stored procedure:
CALL duplicate_table('tableName');
Which will result in a duplicate table called tableName_20181022235959 If called when
SELECT NOW();
results:
2018-10-22 23:59:59
Implementation
DELIMITER $$
CREATE PROCEDURE duplicate_table(IN tableName VARCHAR(255))
BEGIN
DECLARE schemaName VARCHAR(255) DEFAULT SCHEMA();
DECLARE today VARCHAR(14) DEFAULT REPLACE(REPLACE(REPLACE(NOW(), '-', ''), ' ', ''), ':', ''); -- update # year 10000
DECLARE backupTableName VARCHAR(255) DEFAULT CONCAT(tableName, '_', today);
IF fn_table_exists(schemaName, tableName)
THEN
CALL statement(CONCAT('CREATE TABLE IF NOT EXISTS ', backupTableName,' LIKE ', tableName));
CALL statement(CONCAT('INSERT INTO ', backupTableName,' SELECT * FROM ', tableName));
CALL statement(CONCAT('CHECKSUM TABLE ', backupTableName,', ', tableName));
ELSE
SELECT CONCAT('ERROR: Table "', tableName, '" does not exist in the schema "', schemaName, '".') AS ErrorMessage;
END IF;
END $$
DELIMITER ;
DELIMITER $$
CREATE FUNCTION fn_table_exists(schemaName VARCHAR(255), tableName VARCHAR(255))
RETURNS TINYINT(1)
BEGIN
DECLARE totalTablesCount INT DEFAULT (
SELECT COUNT(*)
FROM information_schema.TABLES
WHERE (TABLE_SCHEMA COLLATE utf8_general_ci = schemaName COLLATE utf8_general_ci)
AND (TABLE_NAME COLLATE utf8_general_ci = tableName COLLATE utf8_general_ci)
);
RETURN IF(
totalTablesCount > 0,
TRUE,
FALSE
);
END $$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE statement(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 ;
After I tried the solution above, I come up with my own way.
My solution a little manual and needs DBMS.
First, export the data.
Second, open the export data.
Third, replace old table name with new table name.
Fourth, change all the trigger name in the data (I use MySQL and it show error when I don't change trigger name).
Fifth, import your edited SQL data to the database.
To create table structure only use this below code :
CREATE TABLE new_table LIKE current_table;
To copy data from table to another use this below code :
INSERT INTO new_table SELECT * FROM current_table;
Simple Cloning:
it create a table from another table without taking into account any column attributes and indexes.
CREATE TABLE new_table SELECT * FROM original_table;
Shallow Cloning:
This will only create an empty table base on the structure of the original table
CREATE TABLE new_table LIKE original_table;
The following command would create an empty table base on the original table.
CREATE TABLE adminUsers LIKE users;
Deep Cloning:
This means the new table gets to have all the attributes of each column and indexes of the existing table. This quite useful if you want to maintain the indexes and attributes of the existing table.
CREATE TABLE new_table LIKE original_table;
INSERT INTO new_table SELECT * FROM original_table;
https://towardsdatascience.com/how-to-clone-tables-in-sql-dd29586ec89c
// To copy specific column data use this one:
CREATE TABLE ut_axis_existrec LIKE ut_karvy_annexure; // To create new table
INSERT INTO ut_axis_existrec
(funding_ac,micr_no, warrant_no,
amount,invname,mfundcode,funding_dt,status,remarks1,amc_remark,created_at)
SELECT
t1.funding_ac,
t1.micr_no,
t1.warrant_no,
t1.amount,
t1.invname,
t1.mfund_code,
t1.funding_dt,
t1.status,
t1.remarks1,
t1.created_at
from ut_axis_karvy
inner join
ut_axis_karvy_master as t2
on t1.micr_no = t2.micr_no;
Try this :
`CREATE TABLE new-table (id INT(11) auto_increment primary key) SELECT old-table.name, old-table.group, old-table.floor, old-table.age from old-table;`
I selected 4 columns from old-table and made a new table.
FOR MySQL
CREATE TABLE newtable LIKE oldtable ;
INSERT newtable SELECT * FROM oldtable ;
FOR MSSQL
Use MyDatabase:
Select * into newCustomersTable from oldCustomersTable;
This SQL is used for copying tables, here the contents of oldCustomersTable will be copied to newCustomersTable.
Make sure the newCustomersTable does not exist in the database.