MySQL Dropping Tables - mysql

What syntax for MySQL would I use to drop multiple tables that have a similar pattern to them? Something like:
DROP TABLES FROM `Database1` LIKE "SubTable*"

Since DROP TABLE was supported by prepared statements, it can be done in this way -
SET #tables = NULL;
SELECT GROUP_CONCAT(table_schema, '.', table_name) INTO #tables FROM information_schema.tables
WHERE table_schema = 'Database1' AND table_name LIKE 'SubTable%';
SET #tables = CONCAT('DROP TABLE ', #tables);
PREPARE stmt1 FROM #tables;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;

As noted on this question, the responses given here (Angelin and Devart) won't work in all circumstances without first increasing the limit of group_concat, as per below:
SET group_concat_max_len = 1024 * 1024 * 10;

No. But you can select tables names from information_schema database:
select table_name
from information_schema.tables
where table_schema = 'Database1'
and table_name like 'SubTable%'
And after that iterate the table names in result set and drop them

mysql> SELECT CONCAT( "DROP TABLE ", GROUP_CONCAT(TABLE_NAME) ) AS
stmt
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = "your_db_name" AND TABLE_NAME LIKE "ur condition"
into outfile '/tmp/a.txt';
mysql> source /tmp/a.txt;

Related

How to drop index by passing index name dynamically in my sql?

tried the below query but not working.
SET #index_name = (SELECT INDEX_NAME
FROM information_schema.statistics
WHERE table_schema = 'myDB'
and table_name = 'test'
and column_name = 'col1');
ALTER TABLE test DROP INDEX #index_name;
The index name cannot be retrieved from the variable in the query. Use dynamic SQL, like
SELECT INDEX_NAME
INTO #index_name
FROM information_schema.statistics
WHERE table_schema = 'myDB'
and table_name = 'test'
and column_name = 'col1'
LIMIT 1;
SET #sql := CONCAT('ALTER TABLE myDB.test DROP INDEX ', #index_name);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;

How to mimic pgsql row_to_array()

I wish to get a JSON_OBJECT of a table.
While pgsql has row_to_Json, MySQL does not, and I wish to mimic this.
Of course, I could do this..
SELECT JSON_ARRAYAGG(JSON_OBJECT(id, name)) FROM my_table;
However, if I do not know the names of the fields, and I wish to do something like this:
SELECT JSON_ARRAYAGG(JSON_OBJECT(*)) FROM my_table;
Of course, this does not work. So I tried:
SET #fields = (select group_concat(my_table.res) FROM (SELECT COLUMN_NAME AS res FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='my_table') AS my_table);
SELECT JSON_OBJECT(#fields) FROM my_table;
Which does not work also, because a single string is passed to JSON_OBJECT.
How to get the JSON representation of a row from any table?
You need to use a stored procedure to execute dynamic SQL. The procedure should contain code like this:
SET #fields = (
select group_concat('"', column_name, '", `', column_name, '`')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=table_name_param
);
SET #sql = CONCAT('SELECT JSON_OBJECT(', #fields, ') FROM `', table_name_param, '`';
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Add column to MySQL (not MariaDB) table only if it does not exist using SQL only

I have read this question and the solutions but they are more or less not applicable to my case. I have only SQL option and the PROCEDURE should be avoided, we may not have the required permission.
This is a SQL script that creates missing tables, columns and indexes etc. (schema update)
I see that in MariaDB we can use IF NOT EXISTS clause but this is not available in MySQL. Is there any similar way or workaround available in MySQL?
Using the IF() in a SET statement to come up with the logic works for me:
SET #s = (SELECT IF(
(SELECT COUNT(1)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'your_table'
AND table_schema = 'your_schema'
AND column_name = 'column_name'
) > 0,
"SELECT 1",
"ALTER TABLE your_table ADD column_name VARCHAR(100)"
));
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Is there a easy way to rename a table in procedure?

I am using MariaDB 10.1 SQLyog 11.5
I've renamed the table using below query.
ALTER TABLE old_name RENAME new_name
But there are many stored procedures that reference 'old_name'. I've opened all the SP creation query and changed. Because I don't know which SP has a query that reference old_name table.
Is there a way to know which SP has queries that reference old_name table?
By this INFORMATION_SCHEMA.ROUTINES you can fetch the text available in the stored procedure
Please could try this query: (not verified)
SELECT ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%old_name%'
-- AND ROUTINE_TYPE = "PROCEDURE" -- Filter only if need SPs
ORDER BY ROUTINE_NAME;
Reference from this page
You can it do like this:
Create RENAME Query
SELECT CONCAT ('RENAME TABLE ',
GROUP_CONCAT(t.TABLE_SCHEMA,'.',t.TABLE_NAME,' TO ', t.TABLE_SCHEMA,'.',REPLACE(t.TABLE_NAME,'old','NEW') SEPARATOR ' , ')
) INTO #sql
FROM information_schema.TABLES t
WHERE t.TABLE_TYPE = 'BASE TABLE'
AND t.TABLE_SCHEMA IN ('SCHEMA1','SCHEMA2')
AND t.TABLE_NAME LIKE 'old_table%';
ONLY to verify
SELECT #sql;
Prepare and execute it
PREPARE stmt FROM #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SQL: deleting tables with prefix

How to delete my tables who all have the prefix myprefix_?
Note: need to execute it in phpMyAdmin
You cannot do it with just a single MySQL command, however you can use MySQL to construct the statement for you:
In the MySQL shell or through PHPMyAdmin, use the following query
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_name LIKE 'myprefix_%';
This will generate a DROP statement which you can than copy and execute to drop the tables.
EDIT: A disclaimer here - the statement generated above will drop all tables in all databases with that prefix. If you want to limit it to a specific database, modify the query to look like this and replace database_name with your own database_name:
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_schema = 'database_name' AND table_name LIKE 'myprefix_%';
Some of the earlier answers were very good.
I have pulled together their ideas with some
notions from other answers on the web.
I needed to delete all tables starting with 'temp_'
After a few iterations I came up with this block of code:
-- Set up variable to delete ALL tables starting with 'temp_'
SET GROUP_CONCAT_MAX_LEN=10000;
SET #tbls = (SELECT GROUP_CONCAT(TABLE_NAME)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'my_database'
AND TABLE_NAME LIKE 'temp_%');
SET #delStmt = CONCAT('DROP TABLE ', #tbls);
-- SELECT #delStmt;
PREPARE stmt FROM #delStmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I hope this is useful to other MySQL/PHP programmers.
show tables like 'prefix_%';
copy the results and paste them into a text editor or output the query to a file, use a few search and replaces to remove unwanted formatting and replace \n with a comma
put a ; on the end and add drop table to the front.
you'll get something that looks like this:
drop table myprefix_1, myprefix_2, myprefix_3;
#andre-miller solution is good but there is even better and slightly more professional that will help you execute all in one go. Still will need more than one command but this solution will allow you to use the SQL for automated builds.
SET #tbls = (SELECT GROUP_CONCAT(TABLE_NAME)
FROM information_schema.TABLES
WHERE TABLE_NAME LIKE 'myprefix_%');
PREPARE stmt FROM 'DROP TABLE #tbls';
EXECUTE stmt USING #tbls;
DEALLOCATE PREPARE stmt;
Note: this code is platform dependant, it's for MySQL but for sure it could be implemented for Postgre, Oracle and MS SQL with slight changes.
SELECT CONCAT("DROP TABLE ", table_name, ";")
FROM information_schema.tables
WHERE table_schema = "DATABASE_NAME"
AND table_name LIKE "PREFIX_TABLE_NAME%";
I drop table successfully by edit query to like this
SET GROUP_CONCAT_MAX_LEN=10000;
SET FOREIGN_KEY_CHECKS = 0;
SET #tbls = (SELECT GROUP_CONCAT(CONCAT('`', TABLE_NAME, '`'))
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'pandora'
AND TABLE_NAME LIKE 'temp_%');
SET #delStmt = CONCAT('DROP TABLE ', #tbls);
-- SELECT #delStmt;
PREPARE stmt FROM #delStmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET FOREIGN_KEY_CHECKS = 1;
Just another solution using GROUP_CONCAT so it will execute one drop query like
DROP TABLE table1,table2,..
SET #Drop_Stm = CONCAT('DROP TABLE ', (
SELECT GROUP_CONCAT(TABLE_NAME) AS All_Tables FROM information_schema.tables
WHERE TABLE_NAME LIKE 'prefix_%' AND TABLE_SCHEMA = 'database_name'
));
PREPARE Stm FROM #Drop_Stm;
EXECUTE Stm;
DEALLOCATE PREPARE Stm;
You can do that in one command with MySQL:
drop table myprefix_1, myprefix_2, myprefix_3;
You'll probably have to build the table list dynamically in code though.
An alternative approach would be to use the general purpose routine library for MySQL 5.
I just wanted to post the exact SQL I used - it's something of a mixture of the top 3 answers:
SET GROUP_CONCAT_MAX_LEN=10000;
SET #del = (
SELECT CONCAT('DROP TABLE ', GROUP_CONCAT(TABLE_NAME), ';')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'database_name'
AND TABLE_NAME LIKE 'prefix_%'
);
PREPARE stmt FROM #del;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I found that the prepared statements were a little tricky to get working for me but setting the GROUP_CONCAT_MAX_LEN was essential when you have a lot of tables. This resulted in a simple three-step process with cut-and paste from the mysql command line that worked great for me:
SET GROUP_CONCAT_MAX_LEN=10000;
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_name LIKE 'myprefix_%';
Then carefully cut-and-paste the resulting long DROP statement.