Dropping all schemas with no tables - mysql

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)

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 get list of tables ending with specific name and it's (table's) comment

I have multiple tables in my multiple databases.
On different servers, i use MySQL / PostgreSQL / MS SQL.
I keep short table namesbut the comments given to the tables are with full explanation.
I want query that will show me tables ending with "com" and also the comment given to each table (table's comment).
In MySQL, I know:
SELECT table_name FROM information_schema.tables where table_name like "%com"
But this shows all tables from all databases.
For MySQL, check out following:
SELECT table_name FROM information_schema.tables;
will show all table names in all databases;
SELECT table_name,table_comment FROM information_schema.tables
will show all table names + comment in all databases;
interesting thing, you can fire
SELECT * FROM information_schema.tables;
to know what all info you can get of a table.
SELECT table_name,table_comment FROM information_schema.tables
where
table_schema = 'sifr_b';
will show all table names + comment in "sifr_b" database;
SELECT table_name,table_comment FROM information_schema.tables
where
table_schema = 'sifr_b' and
table_name like "%com";
will show those table names + comment in "sifr_b" database, that have table name ending with "com";

Finding out which tables are different in two versions of a database

I have 2 versions of a database (say db_dev and db_beta). I've made some changes in the db_dev database - added some tables, and changed a few columns in some existing tables. I need to find out the list of table names in which changes have been made.
I can easily find out the tables I've added by running the following query on the information_schema database:
SELECT table_name
FROM tables
WHERE table_schema = 'db_dev'
AND table_name NOT IN (SELECT table_name
FROM tables
WHERE table_schema = 'db_beta');
How do I get the table_names whose column_names do not match in the two database versions?
There are many ready made tools available which can give you changed schema by comparing two databases. Here are some tools which can serve your purpose :
Red-Gate's MySQL Schema & Data Compare
Maatkit
MySQL Diff
SQL EDT
Red-Gate's MySQL Compare is best tool for this purpose. Its paid though but they provide 14 days free trial version if you want to do something temporary.
Using information_schema, here is how it works.
First, you know that the information_schema.COLUMNS table contains the columns definition. If one column has been changed, or a table does not exist, it will reflect in the information_schema.COLUMNS table.
Difficult part is that you have to compare all columns of your COLUMNS table. So, you have to select TABLE_CATALOG,TABLE_NAME,COLUMN_NAME,ORDINAL_POSITION,COLUMN_DEFAULT, and so on (which is subject to evolution depending on your MySQL version).
The column list is the result of the following query:
SELECT GROUP_CONCAT(column_name)
FROM information_schema.COLUMNS
WHERE table_schema="information_schema"
AND table_name="COLUMNS" AND column_name!='TABLE_SCHEMA';
After that, we just have to SELECT TABLE_NAME, <column_list> and search for columns which appear once (column inexistent in other table), or where columns have two different definitions (columns altered). So we will have two different count in the resulting query to consider the two cases.
We will so use a prepared statement to retrieve the list of column we want, and grouping the result.
The resulting query does all the process for you:
SELECT CONCAT(
"SELECT DISTINCT TABLE_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA IN('db_dev', 'db_beta')
GROUP BY table_name, COLUMN_NAME
HAVING count(*)=1 OR
COUNT(DISTINCT CONCAT_WS(',', NULL, ",
GROUP_CONCAT(column_name)
,"))=2;")
FROM information_schema.COLUMNS
WHERE table_schema="information_schema"
AND table_name="COLUMNS" AND column_name!='TABLE_SCHEMA'
INTO #sql;
PREPARE stmt FROM #sql;
EXECUTE #sql;
The following solution does not use an sql query like you tried and does not give you a real list of tables, but it shows you all the changes in both databases.
You can do an sql dump of both database structures :
mysqldump -u root -p --no-data dbname > schema.sql
Then you can compare both files, e.g. using the diff linux tool.

How to delete all MySQL tables beginning with a certain prefix?

I've found another thread on this question, but I wasn't able to use its solutions, so I thought I'd ask with more clarity and detail.
I have a large MySQL database representing a vBulletin forum. For several years, this forum has had an error generated on each view, each time creating a new table named aagregate_temp_1251634200, aagregate_temp_1251734400, etc etc. There are about 20,000 of these tables in the database, and I wish to delete them all.
I want to issue a command that says the equivalent of DROP TABLE WHERE TABLE_NAME LIKE 'aggregate_temp%';.
Unfortunately this command doesn't work, and the Google results for this problem are full of elaborate stored procedures beyond my understanding and all seemingly tailored to the more complex problems of different posters.
Is it possible to write a simple statement that drops multiple tables based on a name like match?
There's no single statement to do that.
The simplest approach is to generate a set of statements, and execute them individually.
We can write a simple query that will generate the statements for us:
SELECT CONCAT('DROP TABLE `',t.table_schema,'`.`',t.table_name,'`;') AS stmt
FROM information_schema.tables t
WHERE t.table_schema = 'mydatabase'
AND t.table_name LIKE 'aggregate\_temp%' ESCAPE '\\'
ORDER BY t.table_name
The SELECT statement returns a rowset, but each row conveniently contains the exact SQL statement we need to execute to drop a table. (Note that information_schema is a builtin database that contains metadata. We'd need to replace mydatabase with the name of the database we want to drop tables from.
We can save the resultset from this query as a plain text file, remove any heading line, and voila, we've got a script we can execute in our SQL client.
There's no need for an elaborate stored procedure.
A little googling found this:
SELECT 'DROP TABLE "' + TABLE_NAME + '"'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'prefix%'
This should generate a script.
Source: Drop all tables whose names begin with a certain string
From memory you have to use prepared statements, for example: plenty of samples on stack exchange
I would recommend this example:
SQL: deleting tables with prefix
The SQL from above, this one includes the specific databasename - it builds it for you
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_schema = 'database_name' AND table_name LIKE 'myprefix_%';
Here is a different way to do it:
MySQL bulk drop table where table like?
This will delete all tables with prefix "mg_"
No need to copy and paste rowsets and in phpadmin copying and pasting is problematic as it will cut off long table names and replace them with '...' ruining set of sql commands.
Also note that '_' is a special character so thats why 'mg_' should be encoded as 'mg\_'
(and FOREIGN_KEY_CHECKS needs to be disabled in order to avoid error messages)
SET FOREIGN_KEY_CHECKS = 0;
SET GROUP_CONCAT_MAX_LEN=32768;
SET #tables = NULL;
SELECT GROUP_CONCAT('`', table_name, '`') INTO #tables
FROM information_schema.tables
WHERE table_schema = (SELECT DATABASE()) and table_name like 'mg\_%';
SELECT IFNULL(#tables,'dummy') INTO #tables;
SET #tables = CONCAT('DROP TABLE IF EXISTS ', #tables);
PREPARE stmt FROM #tables;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET FOREIGN_KEY_CHECKS = 1;

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.