How do I check if table exists before alter table - mysql

I need query to update all tables and set ENGINE = INNODB To many databases. But some of the databases don't have all the same tables; some databases have more tables than others.
So the problem is that
ALTER TABLE `ads` ENGINE = INNODB;
ALTER TABLE `modules` ENGINE = INNODB;
ALTER TABLE `ad_extras` ENGINE = INNODB;
Throws an error when the table modules doe snot exist. I see that I cannot make a direct IF statement' I tried:
IF EXISTS (SHOW TABLES LIKE 'modules') BEGIN
ALTER TABLE `modules` ENGINE = INNODB;
END IF
But it throws
Unrecognized statement type (near IF EXISTS)
Any ideas?

If this is just an ad-hoc task,
select concat('ALTER ', TABLE_NAME, " ENGINE = INNODB;")
from information_schema.TABLES
where TABLE_SCHEMA = '<your schema>';
Execute the output again.

If Exists works only in a stored procedure.
a fixed edition of Jacob's answer:
SET SESSION group_concat_max_len = 1000000;
select group_concat(concat('ALTER Table ', TABLE_NAME, ' ENGINE = INNODB;') SEPARATOR '\n')
from information_schema.TABLES
where TABLE_SCHEMA = 'your_schema_name' and TABLE_TYPE<>'VIEW';
This will give you a script to copy and run separately.

What about testing it simple as this query :
DROP TABLE IF EXISTS `yourtablename`;

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

MYSQL Change Table Engine in Batch

I need to change the whole table in a database engine from Innodb to MyISAMusing MYSQL. How I can do that? Anyone ever do this before? Any helps or suggestions would be appreciated. Thanks!
You can try like this:
SELECT CONCAT('ALTER TABLE `', table_name, '` ENGINE=MyISAM;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'yourdatabase'
AND `ENGINE` = 'Innodb'
AND `TABLE_TYPE` = 'BASE TABLE'
ORDER BY table_name DESC;
The query will give you the ALTER query which you need to execute to change the engines.
Add the ALTER query inside the stored procedure like this:
DROP PROCEDURE IF EXISTS myProc;
DELIMITER //
CREATE PROCEDURE myProc
BEGIN
//Here you can put the ALTER statements.
END//
DELIMITER ;

Remove Foreign Key Relationships From All Tables

I have a database that has several tables. Many of the tables have fields with foreign key constraints. I want to truncate the tables and then repopulate them with new data, and I also want to take off the foreign keys, as some of the relationships have changed. basically, I want to build the FK constraints up from scratch again. How can I remove the current FK constraints from all tables?
You can play with the information_schema.
Take a look at this page
http://dev.mysql.com/doc/refman/5.0/en/key-column-usage-table.html
select concat('alter table ',table_name,' drop foreign key ',constraint_name,';')
from information_schema.key_column_usage
where constraint_schema = 'your_db' and referenced_table_name = 'table_name';
then run the output generated.
You can do something similar in order to truncate all tables.
select concat('truncate ',table_name,';')
from information_schema.tables
where table_schema = 'your_db' and table_type = 'base table'
this one will truncate all tables within the specified database. So use it with care.
I"m guessing you already found a solution, since this post is six months old, but I recently had to come up with a script to drop foreign key constraints to a particular table in MySQL, so that may help anyone else in the same boat:
# create a handy dandy stored procedure
DELIMITER $$
CREATE PROCEDURE DropConstraints(refschema VARCHAR(64), reftable VARCHAR(64), refcolumn VARCHAR(64))
BEGIN
WHILE EXISTS(
SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE 1
AND REFERENCED_TABLE_SCHEMA = refschema
AND REFERENCED_TABLE_NAME = reftable
AND REFERENCED_COLUMN_NAME = refcolumn
) DO
BEGIN
SET #sqlstmt = (
SELECT CONCAT('ALTER TABLE ',TABLE_SCHEMA,'.',TABLE_NAME,' DROP FOREIGN KEY ',CONSTRAINT_NAME)
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE 1
AND REFERENCED_TABLE_SCHEMA = refschema
AND REFERENCED_TABLE_NAME = reftable
AND REFERENCED_COLUMN_NAME = refcolumn
LIMIT 1
);
PREPARE stmt1 FROM #sqlstmt;
EXECUTE stmt1;
END;
END WHILE;
END$$
DELIMITER ;
To run it, simply use:
SET #schema = 'schema_name';
CALL DropConstraints(#schema, 'TableName', 'Referenced_Column_1');
CALL DropConstraints(#schema, 'TableName', 'Referenced_Column_2');
And if you don't want to keep the procedure around:
DROP PROCEDURE DropConstraints;
Of course if you want to drop all FK constraints to the table, you can remove the refcolumn parameter and the last line of each where clause.
ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;

mysql : loop over tables and alter table add index

I have ~1000 tables that start with the same prefix :
table_prefix_{SOME_ID} (i can take the ids from another table)
what is the fast way to loop over all the tables in mysql and do :
ALTER TABLE `table_prefix_{some_id}` ADD INDEX `fields` (`field`)
Forget looping. Just do this:
select concat( 'alter table ', a.table_name, ' add index `fields` (`field`);' )
from information_schema.tables a
where a.table_name like 'table_prefix_%';
Then take the result set and run it as a SQL script.
BTW, you probably mean create index index_name on table_name( column_name);

Using ALTER to drop a column if it exists in MySQL

How can ALTER be used to drop a column in a MySQL table if that column exists?
I know I can use ALTER TABLE my_table DROP COLUMN my_column, but that will throw an error if my_column does not exist. Is there alternative syntax for dropping the column conditionally?
I'm using MySQL version 4.0.18.
For MySQL, there is none: MySQL Feature Request.
Allowing this is arguably a really bad idea, anyway: IF EXISTS indicates that you're running destructive operations on a database with (to you) unknown structure. There may be situations where this is acceptable for quick-and-dirty local work, but if you're tempted to run such a statement against production data (in a migration etc.), you're playing with fire.
But if you insist, it's not difficult to simply check for existence first in the client, or to catch the error.
MariaDB also supports the following starting with 10.0.2:
DROP [COLUMN] [IF EXISTS] col_name
i. e.
ALTER TABLE my_table DROP IF EXISTS my_column;
But it's arguably a bad idea to rely on a non-standard feature supported by only one of several forks of MySQL.
There is no language level support for this in MySQL. Here is a work-around involving MySQL information_schema meta-data in 5.0+, but it won't address your issue in 4.0.18.
drop procedure if exists schema_change;
delimiter ';;'
create procedure schema_change() begin
/* delete columns if they exist */
if exists (select * from information_schema.columns where table_schema = schema() and table_name = 'table1' and column_name = 'column1') then
alter table table1 drop column `column1`;
end if;
if exists (select * from information_schema.columns where table_schema = schema() and table_name = 'table1' and column_name = 'column2') then
alter table table1 drop column `column2`;
end if;
/* add columns */
alter table table1 add column `column1` varchar(255) NULL;
alter table table1 add column `column2` varchar(255) NULL;
end;;
delimiter ';'
call schema_change();
drop procedure if exists schema_change;
I wrote some more detailed information in a blog post.
I know this is an old thread, but there is a simple way to handle this requirement without using stored procedures. This may help someone.
set #exist_Check := (
select count(*) from information_schema.columns
where TABLE_NAME='YOUR_TABLE'
and COLUMN_NAME='YOUR_COLUMN'
and TABLE_SCHEMA=database()
) ;
set #sqlstmt := if(#exist_Check>0,'alter table YOUR_TABLE drop column YOUR_COLUMN', 'select ''''') ;
prepare stmt from #sqlstmt ;
execute stmt ;
Hope this helps someone, as it did me (after a lot of trial and error).
I just built a reusable procedure that can help making DROP COLUMN idempotent:
-- column_exists:
DROP FUNCTION IF EXISTS column_exists;
DELIMITER $$
CREATE FUNCTION column_exists(
tname VARCHAR(64),
cname VARCHAR(64)
)
RETURNS BOOLEAN
READS SQL DATA
BEGIN
RETURN 0 < (SELECT COUNT(*)
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA` = SCHEMA()
AND `TABLE_NAME` = tname
AND `COLUMN_NAME` = cname);
END $$
DELIMITER ;
-- drop_column_if_exists:
DROP PROCEDURE IF EXISTS drop_column_if_exists;
DELIMITER $$
CREATE PROCEDURE drop_column_if_exists(
tname VARCHAR(64),
cname VARCHAR(64)
)
BEGIN
IF column_exists(tname, cname)
THEN
SET #drop_column_if_exists = CONCAT('ALTER TABLE `', tname, '` DROP COLUMN `', cname, '`');
PREPARE drop_query FROM #drop_column_if_exists;
EXECUTE drop_query;
END IF;
END $$
DELIMITER ;
Usage:
CALL drop_column_if_exists('my_table', 'my_column');
Example:
SELECT column_exists('my_table', 'my_column'); -- 1
CALL drop_column_if_exists('my_table', 'my_column'); -- success
SELECT column_exists('my_table', 'my_column'); -- 0
CALL drop_column_if_exists('my_table', 'my_column'); -- success
SELECT column_exists('my_table', 'my_column'); -- 0
Chase Seibert's answer works, but I'd add that if you have several schemata you want to alter the SELECT thus:
select * from information_schema.columns where table_schema in (select schema()) and table_name=...
You can use this script, use your column, schema and table name
IF EXISTS (SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TableName' AND COLUMN_NAME = 'ColumnName'
AND TABLE_SCHEMA = SchemaName)
BEGIN
ALTER TABLE TableName DROP COLUMN ColumnName;
END;
Perhaps the simplest way to solve this (that will work) is:
CREATE new_table AS SELECT id, col1, col2, ... (only the columns you actually want in the final table)
FROM my_table;
RENAME my_table TO old_table, new_table TO my_table;
DROP old_table;
Or keep old_table for a rollback if needed.
This will work but foreign keys will not be moved. You would have to re-add them to my_table later; also foreign keys in other tables that reference my_table will have to be fixed (pointed to the new my_table).
Good Luck...
I realise this thread is quite old now, but I was having the same problem.
This was my very basic solution using the MySQL Workbench, but it worked fine...
get a new sql editor and execute SHOW TABLES to get a list of your tables
select all of the rows, and choose copy to clipboard (unquoted) from the context menu
paste the list of names into another editor tab
write your query, ie ALTER TABLE x DROP a;
do some copying and pasting, so you end up with separate query for each table
Toggle whether the workbench should stop when an error occurs
Hit execute and look through the output log
any tables which had the table now haven't
any tables which didn't will have shown an error in the logs
then you can find/replace 'drop a' change it to 'ADD COLUMN b INT NULL' etc and run the whole thing again....
a bit clunky, but at last you get the end result and you can control/monitor the whole process and remember to save you sql scripts in case you need them again.