Duplicate a schema in mysql database, without dumping sql files and execute them.
It would be great if there is a way to accomplish this task in a few commands.
There are ways to dump an database and import it by executing the sqls generated by an dump program.
But what I would like to do is to execute an command like copy schema abc to abc_bk, and done.
Because I have to do it through phpmyadmin and dumping all fields and re-import them is too time consuming.
There is a statement:
CREATE TABLE <name> LIKE <othername>;
But you would have to do this one table at a time. There is no single statement that does this for all the tables in a schema.
You can get a list of tables from INFORMATION_SCHEMA.TABLES:
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = <old-schema>;
Then for each table returned by that query, run the statement:
CREATE TABLE <new-schema>.<table-name> LIKE <old-schema>.<table-name>;
You must write some code to perform the loop to do this.
Re your comment:
If you want to copy data as well, you can use INSERT ... SELECT.
INSERT INTO <new-schema>.<table-name>
SELECT * FROM <old-schema>.<table-name>;
This will take a while, proportional to the number of rows and number of indexes it needs to update in your table (that is, the cost of writing each row is multiplied by the number of indexes).
Note this does lock the rows it reads from your old table while the INSERT...SELECT is running. If you need to continue writing to the old table while this is going, I would recommend using pt-archiver or pt-table-sync to do the copying.
In my case, I wanted to create a fresh new database based off an existing one, for use with my integration tests. It's basically a fleshed-out version of Bill Karwin's answer above.
Note that my solution does not copy over the data. If you need that functionality, it shouldn't be too difficult to add to the script.
You can reference the GitHub Gist here.
Here is the MySQL code for quick reference:
-- this procedure needs to be run somewhere, so just select a database
USE `existing_db`;
DELIMITER $$
DROP PROCEDURE IF EXISTS `exec`$$
DROP PROCEDURE IF EXISTS `copy_schema`$$
-- simple procedure to allow statement strings to be built and executed easily
-- using `concat`
CREATE PROCEDURE exec(stmt_text TEXT)
BEGIN
SET @sql_text = stmt_text;
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
-- Copies the database `from_db` into a new database, `to_db`.
-- Be careful: This procedure DROPs `to_db` before copying data
CREATE PROCEDURE copy_schema(from_db VARCHAR(64), to_db VARCHAR(64))
BEGIN
-- declare variables to be used throughout the procedure
DECLARE curr_table_name VARCHAR(64) DEFAULT NULL;
DECLARE done TINYINT DEFAULT FALSE;
-- This is a cursor that will point to every row in
-- INFORMATION_SCHEMA.TABLES
-- Each row corresponds to a table in `from_db`, so this will effectively
-- give us a foreach loop through the table names
DECLARE table_cursor
CURSOR FOR
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = from_db;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- initialize `to_db` before attempting to copy data into it
CALL exec(concat('DROP DATABASE IF EXISTS ', to_db));
CALL exec(concat('CREATE DATABASE ', to_db));
OPEN table_cursor;
-- Loop through all table names
table_loop:
LOOP
FETCH NEXT FROM table_cursor INTO curr_table_name;
-- Break if no more results
IF done THEN
LEAVE table_loop;
ELSE
-- Call `CREATE TABLE` for each table, copying the schema from `from_db`
CALL exec(concat('CREATE TABLE ', to_db, '.', curr_table_name, ' LIKE ', from_db, '.', curr_table_name));
END IF;
END LOOP;
CLOSE table_cursor;
END $$
DELIMITER ;
-- EXAMPLE USAGE:
CALL copy_schema('existing_db', 'existing_db_copy');