Convert MyISAM to InnoDB database - mysql

I'm trying to convert a whole database from MyISAM to InnoDB with this statement:
use information_schema;
SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;')
FROM information_schema.tables
WHERE engine = "MyISAM" AND table_type = "BASE TABLE" AND table_schema = "database";
and while I get a result that every table is changed for example:
ALTER TABLE database.action ENGINE=InnoDB;
when I check the table engines they're still MyISAM. The weird thing is that if I run the command separately
ALTER TABLE action ENGINE='InnoDB';
it works fine for that table.
Any tips on how to do the conversion for the whole database?

The SELECT statement you are running only generates strings; the strings it generates are not being executed as SQL statements. You'd need to take the resultset from that query, and then actually execute those statements as a separate step.

Related

Delete all data from multiple tables in mysql

I have a db with 100 tables. I want to delete data from all tables using mysql command or in phpmyadmin
Backup your database structure (use mysqldump with --no-data command line option).
Drop database.
Restore database from the dump.
This method have no problems with FOREIGN KEY relations. Rather than DELETE/TRUNCATE usage where you must clear the tables content in definite order (if you'd clear master table before slave one then the deletion will fail due to referential constraint violation).
Use information_schema.TABLES make dynamic query and exeute.
select concat('delete from ',TABLE_NAME,';') from information_schema.TABLES where TABLE_SCHEMA='databasename';
or try this one
SET FOREIGN_KEY_CHECKS = 0;
SET #TABLES = NULL;
SELECT GROUP_CONCAT('delete from ', table_name,';') INTO #TABLES FROM information_schema.tables
WHERE table_schema = 'databasename' and table_name in ('tbl_audit_trail','tbl_celery');
SET #TABLES= replace( #TABLES,',','');
select #TABLES;
copy the result and execute

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 query Alter table engine only if engine not innodb

I would like to run one query that alter table's engine (ALTER TABLE table1 ENGINE = INNODB) only if the current engine is not INNODB.
How can I do that?
Update:
I got a case of a query trying to alter the table's engine while its already innodb.
You can use
ALTER TABLE t ENGINE = InnoDB;
You can use this query. If db engine already InnoDB then nothing will happen.
Output will be
MySQL returned an empty result set (i.e. zero rows)
if engine not in InnoDB, then it will convert to InnoDB.
The command has no effect if the table is already on InnoDB.
You can query the table engine from information_schema:
SELECT `ENGINE` from `information_schema`.`TABLES`
WHERE `TABLE_SCHEMA`='my_schema' AND `TABLE_NAME`='table1';
http://mysql.rjweb.org/doc.php/myisam2innodb#generating_alters provides several tips about converting from MyISAM to InnoDB, including:
To generate all the ALTERs to convert all the MyISAM tables to InnoDB:
SELECT CONCAT('USE ', table_schema, '; ALTER TABLE ', table_name, ' ENGINE=InnoDB;')
FROM information_schema.tables
WHERE engine = 'MyISAM'
AND table_schema NOT IN ('mysql', 'information_schema', 'performance_schema');
Then copy and paste the output into the mysql commandline tool.

Dropping all schemas with no tables

I want to drop all databases with zero tables I was able to get the databases with tables using
SELECT table_schema, count(table_name) FROM information_schema.tables group by table_schema
But how can I delete the dbs not in this list. I can't do it manually because there are more then 500 dbs there.
About to know schemas without tables, you can try this:
SELECT * FROM information_schema.schemata S
WHERE NOT EXISTS
(SELECT 'TABLE' from information_schema.tables T
WHERE T.table_schema = S.schema_name)
Because in system table SCHEMATA you'll find all schemas of your server and in table TABLES you'll find all tables in all schemas
The upper query must be input on cursor, so you must use a prepared statement to execute your cursor, because your DROP DATABASE has a variable (your schema_table) and it can be ran only with a prepared statement
Used the method posted by #dnoeth in the comments with a slightly diffrent query to get the drop commands and then with some Notepad++ magic executed them to drop all empty databases
SELECT concat('drop database ',schema_name) FROM information_schema.schemata
WHERE schema_name NOT IN
(SELECT TABLE_SCHEMA FROM information_schema.tables)

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.