How to drop all columns with the same name in MySQL [duplicate] - mysql

How I can run a command in phpMyAdmin which will drop all columns in a database that have the prefix test_.

To drop a column from a table, use the syntax:
alter table <tablename> drop column <columnname>
To find all the columns in a table in a database that start with test_, do the following:
select column_name
from INFORMATION_SCHEMA.columns
where table_name = <table_name> and
table_schema = <schema_name> and
left(column_name, 5) = 'test_' -- not using "like" because '_' is a wildcard char
If you were doing this manually, I would recommend running the following query and then pasting the results in to a mysql query interface:
select concat('alter table ', table_name, ' drop column ', column_name)
from INFORMATION_SCHEMA.columns
where table_name = <table_name> and
schema_name = <schema_name> and
left(column_name, 5) = 'test_'
You can do something similar in code, by running the query, returning the results and then running each row as a query.

If you actually want to drop the columns from your schema, you will need to generate the necessary SQL commands dynamically from MySQL's information schema tables. Whilst it is possible to do that within a MySQL stored procedure using SQL prepared statements, which I demonstrate below, you may well find it easier to implement/understand in your preferred development language (which you do not mention in your question):
DELIMITER ;;
CREATE PROCEDURE dropMatchingColumns(IN pattern VARCHAR(64))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR
SELECT CONCAT(
'ALTER TABLE `', REPLACE( TABLE_NAME, '`', '``'), '` ',
GROUP_CONCAT(
'DROP COLUMN `', REPLACE(COLUMN_NAME, '`', '``'), '`'
)
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE pattern AND TABLE_SCHEMA = DATABASE()
GROUP BY TABLE_NAME
;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO #sql;
IF done THEN
LEAVE read_loop;
END IF;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE cur;
END;;
DELIMITER ;
With this procedure defined, one need only CALL dropMatchingColumns('test\_%'); in order to drop all the columns prefixed with test_ from the current database.

If you have MySQl Workbench then you can delete multiple columns by simply do a mass selection and telling workbench to do a mass deletion of the selected columns

I would like to explain or simplify this answer for those like me who were having trouble with this.
I was having trouble dropping a column with the name 'seq' in all tables in my database 'demo'.
You can create a selection with the commands formatted for each table using something like this:
Select concat('alter table ', table_name, ' drop column ', 'seq;')
from (select table_name
from INFORMATION_SCHEMA.tables
where table_name = table_name and
table_schema = 'demo') as t
This creates the alter table command for each table in the 'demo' database.
You have to select the result, copy it, and paste it back into the query editor.
It's a two step process, but if you have to do this several times, save the commands in a text file to run again later.

Related

Create a new MySQL Database from existing db with up to 10000 rows of data from each table

I am trying to create a database with some data not all. I don't need 1M+ records to do what I need so I am okay with only 10000 rows.
I figured I can use a stored procedure to loop through all the table and manually create each table and insert only 10000 rows.
I created a stored procedure like this
CREATE DEFINER=`root`#`10.%` PROCEDURE `createNewDatabase`(in db_name varchar(100), in new_db_name varchar(100))
BEGIN
DECLARE finish INT DEFAULT 0;
DECLARE tbl VARCHAR(100);
DECLARE cur_tables CURSOR FOR SELECT table_name FROM information_schema.tables WHERE table_schema = db_name AND TABLE_TYPE='BASE TABLE';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finish = 1;
OPEN cur_tables;
my_loop: LOOP
FETCH cur_tables INTO tbl;
IF finish = 1 THEN
LEAVE my_loop;
END IF;
SET #str = CONCAT('DROP TABLE IF EXISTS `', new_db_name, '`.`' , tbl , '`; CREATE TABLE `', new_db_name, '`.`' , tbl , '` LIKE `', db_name , '`.`', tbl,'`; INSERT INTO `', new_db_name , '`.`' , tbl, '` SELECT * FROM `', db_name ,'`.`', tbl , '` LIMIT 10000;');
PREPARE stmt FROM #str;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE cur_tables;
END
Then I called it like this
CALL createNewDatabase('baseTable', 'newTable');
But I run the procedure I get the following error
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CREATE TABLE `newTable`.`account_addresses` LIKE `baseTable`.`account_addres' at line 1
if I added the following 2 lines after just before the prepare statement
SELECT #str;
LEAVE my_loop;
I get the following queries which works if I executed them manually
DROP TABLE IF EXISTS `newTable`.`account_addresses`;
CREATE TABLE `newTable`.`account_addresses` LIKE `baseTable`.`account_addresses`;
INSERT INTO `newTable`.`account_addresses` SELECT * FROM `newTable`.`account_addresses` LIMIT 10000;
CREATE TABLE `newTable`.`account_addresses` LIKE `baseTable`.`account_addresses`; INSERT INTO `newTable`.`account_addresses` SELECT * FROM `baseTable`.`account_addresses` LIMIT 10000;
What am I doing wrong here? Why it is erroring?
Quote from mysql's documentation on PREPARE:
The text must represent a single statement, not multiple statements.
You are trying to execute a drop table and a create table statement, insert records in 1 prepared statement and this is not allowed. Have 3 separate prepared statement for the 3 commands.

How to convert an SQL select query into a formatted HTML table within a MySQL function

I'm looking for a way to generate valid HTML code within MySQL (without PHP) by converting any query output into an HTML table.
Here's my progress so far and evidently, I'm stuck. I hope I can get some help, thanks.
1. "dynSQL" - A procedure to take any Select query and create a named table out of it
Since MySQL doesn't allow dynamic queries in functions, I'm calling a procedure that creates a named table, tmp. I can't use a temporary table because info about temporary tables is not available in information_schema (in mysql 5.6)
CREATE DEFINER=`root`#`%` PROCEDURE `dynSQL`(SQL_QUERY TEXT)
BEGIN
set #SQLQ := 'Drop table if exists tmp;';
PREPARE stmt from #SQLQ;
Execute stmt;
SET #SQLQ := concat('create table tmp as ',SQL_QUERY);
PREPARE stmt from #SQLQ;
Execute stmt;
-- I'm adding a auto increment ID column to be able to loop through the rows later
SET #SQLQ := "ALTER TABLE tmp add column CustColHTML_ID INT NOT NULL AUTO_INCREMENT FIRST, ADD primary KEY Id(CustColHTML_ID)";
PREPARE stmt from #SQLQ;
Execute stmt;
DEALLOCATE PREPARE stmt;
END
2. "MakeHTML" - Function to read from the table tmp and return a formatted HTML table
CREATE DEFINER=`root`#`%` FUNCTION `MakeHTML`() RETURNS text CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE HTML text default "<TABLE><TR>";
DECLARE rowCount int default 0;
DECLARE i int default 0;
select concat('<TR>',group_concat('<TD>',column_name,'</TD>' separator ''),'</TR>') into html from information_Schema.`columns` where table_name='tmp';
Select max(CustColHTML_ID) into rowCount from `tmp`; -- Set the row counter
WHILE i<=rowCount DO
-- What do I do here? How do I loop through the columns of table tmp?
set i:=i+1;
END WHILE;
RETURN HTML;
END
As you can see, I'm stuck at looping through the unknown and dynamic columns of table tmp. I read about how a cursor can be used here, but all the examples I saw make use of known columns and assign those into named variables. However, since the query itself is dynamic, I wouldn't know the names of the columns.
I'd really appreciate your time and assistance, thanks!
p.s. I've posted this as a new question because my earlier question was marked as closed as being too broad. I subsequently edited my question but it was still showing as Closed. I've therefore deleted the older question and replaced it with this one.
With a sample table as such:
CREATE TABLE tmp (ID INT, Col1 INT, Col2 INT);
The SQL you would need to generate your HTML is:
SELECT CONCAT('<table>', GROUP_CONCAT(CONCAT('<tr><td>',ID,'</td><td>',Col1,'</td><td>',Col2,'</td><tr>')), '</table>')
FROM tmp;
You can generate this using the INFORMATION_SCHEMA:
SELECT CONCAT
(
'SELECT CONCAT(''<table>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp';
It is then just a case of executing this:
SET #SQL = (
SELECT CONCAT
(
'SELECT CONCAT(''<table>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Example on SQL Fiddle
ADDENDEUM
Forgot to include table headers:
SET #SQL = (
SELECT CONCAT
(
'SELECT CONCAT(''<table><tr>'',',
GROUP_CONCAT(CONCAT('''<th>'',''', COLUMN_NAME, ''',''</th>''')),
', ''</tr>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Example on SQL Fiddle

Mysql - use query results for another query

I want to find some specific Columns of a database from Information_schema.Columns and edit those columns type. I don't know how can I use the result of my first query from Information_schema for making another query to edit columns.
Also I have to do it in MySQL, not PHP.
I've read about Procedures a little , but it was confusing. Acutally I've never done much with mysql.
I would really appreciate if anyone can show me the path or any tutorial.
thanks in advance
this could be what you are looking for. dynamic alter query:
SELECT CONCAT('ALTER TABLE `my_table` ',
GROUP_CONCAT(' CHANGE COLUMN `', COLUMN_NAME , '` ',
' `', COLUMN_NAME , '` DECIMAL (14,4)'))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'my_db' AND TABLE_NAME = 'my_table'
INTO #sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
you can use a cursor in stored procedure to apply this to all tables.
DECLARE curs CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'my_db';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
OPEN curs;
SET bDone = 0;
REPEAT
FETCH curs INTO table_name;
IF table_name
/*alter query*/
END IF;
UNTIL bDone END REPEAT;
CLOSE curs;

Command to drop all columns in a database that have prefix test_ to run

How I can run a command in phpMyAdmin which will drop all columns in a database that have the prefix test_.
To drop a column from a table, use the syntax:
alter table <tablename> drop column <columnname>
To find all the columns in a table in a database that start with test_, do the following:
select column_name
from INFORMATION_SCHEMA.columns
where table_name = <table_name> and
table_schema = <schema_name> and
left(column_name, 5) = 'test_' -- not using "like" because '_' is a wildcard char
If you were doing this manually, I would recommend running the following query and then pasting the results in to a mysql query interface:
select concat('alter table ', table_name, ' drop column ', column_name)
from INFORMATION_SCHEMA.columns
where table_name = <table_name> and
schema_name = <schema_name> and
left(column_name, 5) = 'test_'
You can do something similar in code, by running the query, returning the results and then running each row as a query.
If you actually want to drop the columns from your schema, you will need to generate the necessary SQL commands dynamically from MySQL's information schema tables. Whilst it is possible to do that within a MySQL stored procedure using SQL prepared statements, which I demonstrate below, you may well find it easier to implement/understand in your preferred development language (which you do not mention in your question):
DELIMITER ;;
CREATE PROCEDURE dropMatchingColumns(IN pattern VARCHAR(64))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR
SELECT CONCAT(
'ALTER TABLE `', REPLACE( TABLE_NAME, '`', '``'), '` ',
GROUP_CONCAT(
'DROP COLUMN `', REPLACE(COLUMN_NAME, '`', '``'), '`'
)
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE pattern AND TABLE_SCHEMA = DATABASE()
GROUP BY TABLE_NAME
;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO #sql;
IF done THEN
LEAVE read_loop;
END IF;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE cur;
END;;
DELIMITER ;
With this procedure defined, one need only CALL dropMatchingColumns('test\_%'); in order to drop all the columns prefixed with test_ from the current database.
If you have MySQl Workbench then you can delete multiple columns by simply do a mass selection and telling workbench to do a mass deletion of the selected columns
I would like to explain or simplify this answer for those like me who were having trouble with this.
I was having trouble dropping a column with the name 'seq' in all tables in my database 'demo'.
You can create a selection with the commands formatted for each table using something like this:
Select concat('alter table ', table_name, ' drop column ', 'seq;')
from (select table_name
from INFORMATION_SCHEMA.tables
where table_name = table_name and
table_schema = 'demo') as t
This creates the alter table command for each table in the 'demo' database.
You have to select the result, copy it, and paste it back into the query editor.
It's a two step process, but if you have to do this several times, save the commands in a text file to run again later.

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.