Copying Tables Without Data in MySQL Retaining Auto Increment - mysql

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.

Related

Stored Procedure to read text file and loop through it

I tried looking through a lot of threads on this but couldn't find anything that works for me.
I have a text file with list of table names (about 100 out of 300 total tables in the schema).
tables.txt
table1
table2
table3
I am writing a stored procedure and want to loop through the table names in that text file and inject the table names in the query.
Something like this
While (line = readline) != null do
update line set col1='foo' where id=x;
End while;
Is something like that even possible in a stored procedure? using (mysql 5.6). and I am using Workbench 6.3 CE
Since you want to run the same code for every table in your database.You can create your command using Information Schema
USE INFORMATION_SCHEMA;
SELECT
CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` ALTERING CODE HERE;")
AS MySQLCMD FROM TABLES
WHERE TABLE_SCHEMA = "your_schema_goes_here";
When the commands are created then you can copy and run all of them.
UPDATE If you want to update a column common between all those tables you can write it as follow
SELECT CONCAT("UPDATE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` SET COLUMN_NAME = VALUE [ANY WHERE CLAUSE]") as MySQLCMD from TABLES where TABLE_SCHEMA = "YourSchemaName";
UPDATE2 Generating commands for specific tables.
SELECT
CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` ALTERING CODE HERE;")
AS MySQLCMD FROM TABLES
WHERE TABLE_SCHEMA = "your_schema_goes_here" AND TABLE_NAME IN ('Table1', 'TAble2');
In general I would take this approach. There is not enough detail to be more specific. Note, this uses dynamic SQL rather than a stored procedure.
Backup your database!!
Create a temporary table. (either real or in memory depending on how long you need this data retained)
Parse the text file into a temporary table using something like this:
LOAD DATA INFILE '/tmp/mylist.txt' INTO TABLE MyTempList;
Create a test a single ALTER table statement. Once you know it works exactly as intended...
Convert your working ALTER statement into dynamic SQL that selects the table names from your temporary table. Something like this: Alter table using sub select
When complete, you can delete your temporary table.
Alternately, you could put a single ALTER statement into a stored procedure, asking for the table name as a parameter. But then you will still need to parse the text file using something like steps 1-3. And then use a cursor to loop over the table names and call the stored procedure.

MySQl Bulk Rename, Alter , Update

I have a MySQl database with more than 200 tables. I want to do following on ALL tables in this database.
Update all table name by adding a constant to the name
Add column (Alter table) to each table
Update each table to set newly added column
Can someone please suggest an efficient way of doing this
Thanks
bhim
You need to write a couple of SQL statements that will generate the rename / add column SQL statements.
Then you can run the SQL Statements.
You haven't provided table names, or schemas, etc. so I can give guidance but not exact results.
So assuming your "adding a constant to the name" is prefixing "const_" to it, you could do something like:
SELECT 'RENAME TABLE ''' || table_name || ''' TO ''const_' || table_name || ''' FROM information_schema.tables WHERE table_catalog = 'YourCatalog' and table_schema = 'YourSchema';
This would give you the rename table command as the output, which you could pick up and put in a text editor to tidy up.
You'll need to execute a few queries against INFORMATION_SCHEMA.tables to figure out the right filter to get the right criteria for the tables list.
And you can do similar for the Add column statement.
Some useful references:
Information schema: https://dev.mysql.com/doc/refman/5.7/en/tables-table.html
Rename a table: https://blog.marceloaltmann.com/en-how-to-rename-table-in-mysql-pt-como-renomear-tabelas-no-mysql/
Add a column: http://www.mysqltutorial.org/mysql-add-column/

How would I delete a single column in all tables in MYSQL

I have a column 'seq' in every table of my database that I would like to delete easily.
I have to do this on occasion in MySQL and am hoping this can be automated.
There isn't a simple magical expression to just do this. You need to generate a list of SQL statements and then run them, somehow.
(Most database folks don't routinely drop columns from a database in production; it takes a lot of time during which the tables are inaccessible, and it's destructive. A fat-finger error could really mess you up.)
You might start by using the information_schema in MySQL to discover which of your tables have a seq column in them. This query will return that list of tables for the database you're currently using.
SELECT DISTINCT TABLE_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND COLUMN_NAME = 'seq'
You could then adapt that query to, for example, create a list of statements like this.
SELECT DISTINCT
CONCAT('UPDATE ',TABLE_NAME, ' SET seq = 0;') AS stmt
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND COLUMN_NAME = 'seq'
This will produce a result set like this:
UPDATE table_a SET seq = 0;
UPDATE table_b SET seq = 0;
UPDATE user SET seq = 0;
Then you could run these statements one by one. These statements will zero out your seq columns.
Edit
You can also do
CONCAT('ALTER TABLE ',TABLE_NAME, ' DROP COLUMN seq;') AS stmt
to get a drop column statement for each table.
But, you might consider creating views of your tables that don't contain the seq columns, and then exporting to PostgreSQL using those views. If your tables are significant in size, this will save you a lot of time.

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

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;

How to assume a table prefix on a entire MySQL script?

I have a script to run in my database.
But the problem is this script assume the tables have no prefix on it and all databases have a prefix (let call it prefix_).
Is there a command or a way to MySQL try to run
INSERT INTO prefix_mytable ...
instead of
INSERT INTO mytable...
for all of sql queries at the script (UPDATE, INSERT and DELETE)?
There is no way in MySQL to automatically prefix tables in the way you're describing. #MichaelBerkowski is correct.
The best I can suggest is that you create a second database with updateable views, using unprefixed names, as front-ends to your prefixed table names.
Here's an example:
mysql> CREATE DATABASE test;
mysql> CREATE TABLE test.prefix_mytable (id INT PRIMARY KEY, x VARCHAR(20));
mysql> CREATE DATABASE test2;
mysql> CREATE VIEW test2.mytable AS SELECT * FROM test.prefix_mytable;
Now you can insert using the unprefixed names:
mysql> INSERT INTO test2.mytable (id, x) VALUES (123, 'abc');
And to verify that the data was inserted into your original table:
mysql> SELECT * FROM test.prefix_mytable;
Once you do that, you can run your SQL script against database test2 and all the INSERTs should get to your original tables all right.
If you have a lot of tables you need to create views for, you can automate the creation of the CREATE VIEW statements:
mysql> SELECT CONCAT('CREATE VIEW test2.', REPLACE(TABLE_NAME, 'prefix_', ''),
' AS SELECT * FROM test.', TABLE_NAME, ';') AS _sql
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME LIKE 'prefix\_%';
Here is the guide to replace WordPress table prefix from wp_ to a different, like this you can update any mysql table. How to rename WordPress tables prefix?