How to add prefix of all tables in mysql - mysql

How can I add prefix to all tables in mysql using query.
For example:
I need to add "dr_" in all tables which are available in mysql database.

Run all queries that you get from running this query:
SELECT Concat('ALTER TABLE `', TABLE_NAME, '` RENAME TO `dr_', TABLE_NAME, '`;') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '<name of your db>';

For this example, I will create a database called prefixdb with 4 tables:
mysql> drop database if exists prefixdb;
Query OK, 4 rows affected (0.01 sec)
mysql> create database prefixdb;
Query OK, 1 row affected (0.00 sec)
mysql> use prefixdb
Database changed
mysql> create table tab1 (num int) ENGINE=MyISAM;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab2 like tab1;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab3 like tab1;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab4 like tab1;
Query OK, 0 rows affected (0.04 sec)
mysql> show tables;
+--------------------+
| Tables_in_prefixdb |
+--------------------+
| tab1 |
| tab2 |
| tab3 |
| tab4 |
+--------------------+
4 rows in set (0.00 sec)
The query to generate it would be
select
concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';')
from
(select table_schema db,table_name tb
from information_schema.tables where
table_schema='prefixdb') A,
(SELECT 'dr_' prfx) B
;
Running it at the command line I get this:
mysql> select concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') from (select table_schema db,table_name tb from information_schema.tables where table_schema='prefixdb') A,(SELECT 'dr_' prfx) B;
+----------------------------------------------------------------+
| concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') |
+----------------------------------------------------------------+
| alter table prefixdb.tab1 rename prefixdb.dr_tab1; |
| alter table prefixdb.tab2 rename prefixdb.dr_tab2; |
| alter table prefixdb.tab3 rename prefixdb.dr_tab3; |
| alter table prefixdb.tab4 rename prefixdb.dr_tab4; |
+----------------------------------------------------------------+
4 rows in set (0.00 sec)
Pass the result back into mysql like this:
mysql -hhostip -uuser -pass -AN -e"select concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') from (select table_schema db,table_name tb from information_schema.tables where table_schema='prefixdb') A,(SELECT 'dr_' prfx) B" | mysql -hhostip -uuser -ppass -AN
With regard to your question if you want to rename all tables, do not touch information_schema and mysql databases. Use this query instead:
select
concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';')
from
(select table_schema db,table_name tb
from information_schema.tables where
table_schema not in ('information_schema','mysql')) A,
(SELECT 'dr_' prfx) B
;
Give it a Try !!!

In case anyone runs into this error:
#1044 - Access denied for user 'user_name'#'localhost' to database 'information_schema'
After executing the queries resulting from the answer posted by #abhay, use the following instead to eliminate the issue:
SELECT Concat('RENAME TABLE `', TABLE_NAME, '` TO `dr_', TABLE_NAME, '`;') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '<database_name>'

To add to Rolando's excellent and comprehensive answer. If you run the RENAME queries generated by his SELECT CONCAT query (I used phpMyAdmin and just copied the output queries into the SQL box and hit Go) then you shouldn't have any problems with foreign key constraints. I've just done this on a test database in XAMPP and all tables renamed ok, and the constraints remained intact. This may seem obvious to SQL experts but perhaps not so much to us amateurs.

Add a prefix to all of your database tables.
Supposing that your database was called "my_database" and the prefix you want to add is "my_prefix", execute the following query:
SELECT Concat('ALTER TABLE ', TABLE_NAME, ' RENAME TO my_prefix_', TABLE_NAME, ';') FROM information_schema.tables WHERE table_schema = 'my_database'
Your result set will be a bunch of queries that you can copy and paste into your favorite MySQL editor (Sequel Pro, phpMyAdmin, whatever). Just paste those in and execute, and you're all done.

Related

MySQL query - get a list of ALL WP admin email addresses for all WP sites on server

I have a lot of WP websites set up on my server, and I'm trying to get a list of admin email addresses registered for all of the WP sites.
The server uses WHM/cPanel, and MariaDB.
I'd hoped WordPress Toolkit could do this out of the box, but it doesn't seem to be able to.
I'm an SQL noob, and I've only gotten as far as this for my SQL query, for a single DB:
SELECT option_value
FROM `database_name`.`wp_options`
WHERE option_name="admin_email"
Another problem is, lots of the WP databases on the server don't use the standard wp_ table prefix, but instead use a random string, so I also need a way of using a wildcard in the table name like
*_options
So my 2 problems are:
Make the query loop across ALL databases on the server
make the query use a wildcard in the table name
Is this possible?
Yes. Its two queries, first to generate the SQL, and then execute it.
Example setup:
MariaDB [(none)]> create database rr;
Query OK, 1 row affected (0.000 sec)
MariaDB [(none)]> create database ss;
Query OK, 1 row affected (0.001 sec)
MariaDB [(none)]> create table ss.wp_options(option_name varchar(30), option_value varchar(30));
Query OK, 0 rows affected (0.003 sec)
MariaDB [(none)]> create table rr.rr_options(option_name varchar(30), option_value varchar(30));
Query OK, 0 rows affected (0.003 sec)
MariaDB [(none)]> insert into ss.wp_options values ('admin_email', 'me#ss');
Query OK, 1 row affected (0.003 sec)
MariaDB [(none)]> insert into rr.rr_options values ('admin_email', 'me#rr');
Query OK, 1 row affected (0.002 sec)
Then use the information_schema.TABLES to generate your query using UNION ALL to concatinate them:
SELECT group_concat(
concat('select "', TABLE_SCHEMA, '" as db, option_value from ', TABLE_SCHEMA, '.', TABLE_NAME, ' WHERE option_name="admin_email"')
SEPARATOR ' UNION ALL ') INTO #sql
FROM information_schema.TABLES
WHERE TABLE_NAME LIKE '%_options';
Just to show what we generate:
MariaDB [(none)]> select #sql\G
*************************** 1. row ***************************
#sql: select "ss" as db, option_value from ss.wp_options WHERE option_name="admin_email"
UNION ALL select "rr" as db, option_value from rr.rr_options WHERE option_name="admin_email"
Execute immediate runs a query, like a prepared statement without the setup and run, shutdown steps:
MariaDB [(none)]> execute immediate #sql;
+----+--------------+
| db | option_value |
+----+--------------+
| ss | me#ss |
| rr | me#rr |
+----+--------------+
2 rows in set (0.002 sec)

get primary keys of underlaying tables in a view

I know of show tables and show columns from table TABLE_NAME which gets me the primary key (Key is PRI). But how do I get the primary key of a view or more specific the keys of the underlying tables? In that case show columns from VIEW_NAME all the Key values are empty.
A new INFORMATION_SCHEMA table exists to map views to the underlying table(s). It's called VIEW_TABLE_USAGE.
mysql> create table mytable (id serial primary key);
Query OK, 0 rows affected (0.01 sec)
mysql> create view v as select * from mytable;
Query OK, 0 rows affected (0.00 sec)
mysql> select table_schema, table_name, column_name, ordinal_position
from information_schema.view_table_usage
join information_schema.key_column_usage using (table_schema, table_name)
where table_name='mytable' and constraint_name='PRIMARY';
+--------------+------------+-------------+------------------+
| TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME | ORDINAL_POSITION |
+--------------+------------+-------------+------------------+
| test2 | mytable | id | 1 |
+--------------+------------+-------------+------------------+
This table is new in MySQL 8.0.13.
If you use an older version of MySQL (or any version of MariaDB), there is no such information_schema table, so you can't get this information by any query. You would need to come up with a way to parse the view definition, which is a complex task because it could have a wide variety of SELECT syntax.
mysql> select view_definition from information_schema.views where table_name='v';
+--------------------------------------------------------------+
| VIEW_DEFINITION |
+--------------------------------------------------------------+
| select `test2`.`mytable`.`id` AS `id` from `test2`.`mytable` |
+--------------------------------------------------------------+

How to create tables with a prefix in a more maintainable way

I need to maintain a SQL script (for MySQL) which creates many tables with same prefix, like wp_parent, wp_teacher.
I don't want to write CREATE TABLE wp_parent. In that case, if I need to change the prefix, I have to modify many lines.
I have tried to use MySQL user variable, but it didn't work.
Is there any way to make prefix be a variable and then use the variable in other statement?
Or is there any other method to make the script more maintainable?
Your can use this command to add the prefix to the tables in database
SELECT Concat('ALTER TABLE ', TABLE_NAME, ' RENAME TO dr_', TABLE_NAME, ';')
FROM INFORMATION_SCHEMA.TABLES;
Give it a Try !!!
mysql> drop database if exists prefixdb;
Query OK, 4 rows affected (0.01 sec)
mysql> create database prefixdb;
Query OK, 1 row affected (0.00 sec)
mysql> use prefixdb
Database changed
mysql> create table tab1 (num int) ENGINE=MyISAM;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab2 like tab1;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab3 like tab1;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab4 like tab1;
Query OK, 0 rows affected (0.04 sec)
mysql> show tables;
+--------------------+
| Tables_in_prefixdb |
+--------------------+
| tab1 |
| tab2 |
| tab3 |
| tab4 |
+--------------------+
4 rows in set (0.00 sec)
The query to generate it would be
select
concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';')
from
(select table_schema db,table_name tb
from information_schema.tables where
table_schema='prefixdb') A,
(SELECT 'dr_' prfx) B
;
Running it at the command line I get this:
mysql> select concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') from (select table_schema db,table_name tb from information_schema.tables where table_schema='prefixdb') A,(SELECT 'dr_' prfx) B;
+----------------------------------------------------------------+
| concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') |
+----------------------------------------------------------------+
| alter table prefixdb.tab1 rename prefixdb.dr_tab1; |
| alter table prefixdb.tab2 rename prefixdb.dr_tab2; |
| alter table prefixdb.tab3 rename prefixdb.dr_tab3; |
| alter table prefixdb.tab4 rename prefixdb.dr_tab4; |
+----------------------------------------------------------------+
4 rows in set (0.00 sec)
Pass the result back into mysql like this:
mysql -hhostip -uuser -pass -AN -e"select concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') from (select table_schema db,table_name tb from information_schema.tables where table_schema='prefixdb') A,(SELECT 'dr_' prfx) B" | mysql -hhostip -uuser -ppass -AN
With regard to your question if you want to rename all tables, do not touch information_schema and mysql databases. Use this query instead:
select
concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';')
from
(select table_schema db,table_name tb
from information_schema.tables where
table_schema not in ('information_schema','mysql')) A,
(SELECT 'dr_' prfx) B ;

MySQL SELECT * fails on temporary table created by PREPARE using dynamic column and table names after first pass

MySQL 5.2, CentOS 6.4.
MySQL SELECT * fails on temporary table created by PREPARE using dynamic column and table names after first pass, when column name and table name are changed to different values from the first pass.
The work-around is to use a column alias that remains the same from pass to pass.
DROP PROCEDURE IF EXISTS test1;
DELIMITER $$
CREATE PROCEDURE test1( column_name VARCHAR(20), table_name VARCHAR(20) )
BEGIN
SET #prepared_stmt_arg = 'prepared_stmt_arg_value';
DROP TABLE IF EXISTS tmp1;
CREATE TEMPORARY TABLE tmp1
SELECT 1 AS col_tmp1;
DROP TABLE IF EXISTS tmp2;
CREATE TEMPORARY TABLE tmp2
SELECT 2 AS col_tmp2;
# drop tmp table if it exists
DROP TABLE IF EXISTS tmp_test1;
# prepared statement
SET #prepared_stmt =
CONCAT("
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, ", column_name, " # AS constant_col_alias
FROM ", table_name, "
"); # END statement
# display prepared statement before executing it
SELECT #prepared_stmt;
# prepare the statement
PREPARE ps FROM #prepared_stmt;
# execute
EXECUTE ps USING #prepared_stmt_arg;
# deallocate
DEALLOCATE PREPARE ps;
# display
SELECT * FROM tmp_test1;
END $$
DELIMITER ;
The SELECT statement at the very end of the procedure fails. (You may need to scroll down to see the error message.)
mysql> CALL test1('col_tmp1', 'tmp1');
+---------------------------------------------------------------------------------------------------------------------------------+
| #prepared_stmt |
+---------------------------------------------------------------------------------------------------------------------------------+
|
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, col_tmp1 # AS constant_col_alias
FROM tmp1
|
+---------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
+-------------------------+----------+
| prepared_stmt_arg | col_tmp1 |
+-------------------------+----------+
| prepared_stmt_arg_value | 1 |
+-------------------------+----------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> CALL test1('col_tmp2', 'tmp2');
+---------------------------------------------------------------------------------------------------------------------------------+
| #prepared_stmt |
+---------------------------------------------------------------------------------------------------------------------------------+
|
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, col_tmp2 # AS constant_col_alias
FROM tmp2
|
+---------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
ERROR 1054 (42S22): Unknown column 'dev.tmp_test1.col_tmp1' in 'field list'
However, if you uncomment the column alias (remove the # just before AS constant_col_alias), all works well. (You may need to scroll down to see Query OK.)
mysql> CALL test1('col_tmp1', 'tmp1');
+-------------------------------------------------------------------------------------------------------------------------------+
| #prepared_stmt |
+-------------------------------------------------------------------------------------------------------------------------------+
|
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, col_tmp1 AS constant_col_alias
FROM tmp1
|
+-------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
+-------------------------+--------------------+
| prepared_stmt_arg | constant_col_alias |
+-------------------------+--------------------+
| prepared_stmt_arg_value | 1 |
+-------------------------+--------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> CALL test1('col_tmp2', 'tmp2');
+-------------------------------------------------------------------------------------------------------------------------------+
| #prepared_stmt |
+-------------------------------------------------------------------------------------------------------------------------------+
|
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, col_tmp2 AS constant_col_alias
FROM tmp2
|
+-------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
+-------------------------+--------------------+
| prepared_stmt_arg | constant_col_alias |
+-------------------------+--------------------+
| prepared_stmt_arg_value | 2 |
+-------------------------+--------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Well it seems to be a bug or a feature (if you want) up to version 5.6.
See Bug #32868 Stored routines do not detect changes in meta-data.
Workaround: flush the stored routine cache by doing this:
CREATE OR REPLACE VIEW tmpview AS SELECT 1;
Here is SQLFiddle demo MySql 5.1.X
Here is SQLFiddle demo MySql 5.5.X
If you comment out CREATE OR REPLACE VIEWtmpviewAS SELECT 1 you'll get your error.
Here is SQLFiddle demo MySql 5.6.X shows that it's no longer a problem
Now you have at least these options to go with:
don't use SELECT * use explicit column names instead.
use proposed workaround
upgrade to 5.6.X

mysql trouble with information_schema.tables

-edit2- 3hrs later and still have the same problem. I am using the noinstall archive package.
-edit- maybe someone can tell me a better way to check if a table exist?
I have a function in my lib to check if a table exist which i asked how to do in the past.
I deleted my database and created it again. My code didnt create the tables properly. After debugging i decided to write the below.
mysql> SELECT table_schema, table_name FROM information_schema.tables WHERE tabl
e_schema = 'mydb' AND table_name='ApprovePost';
+--------------+-------------+
| table_schema | table_name |
+--------------+-------------+
| mydb | ApprovePost |
+--------------+-------------+
1 row in set (0.00 sec)
Weird... mydb was dropped and created again (i wrote drop database mydb; and create database mydb;. It should be gone?). Lets find out what exists
mysql> SELECT table_schema, table_name FROM information_schema.tables WHERE tabl
e_schema = 'mydb';
Empty set (0.00 sec)
Not only do i not know why the first statement shows tables which is wrecking my code, i dont know why this is not showing any tables (in that database).
note: The databases should all be innodb. Also this is a fresh windows install and i may have configured something wrong.
Bonus weirdness.
mysql> drop database mydb;
ERROR 1008 (HY000): Can't drop database 'mydb'; database doesn't exist
mysql> SELECT table_schema, table_name FROM information_schema.tables WHERE tabl
e_schema = 'mydb';
Empty set (0.00 sec)
mysql> SELECT table_schema, table_name FROM information_schema.tables WHERE tabl
e_schema = 'mydb' AND table_name='ApprovePost';
+--------------+-------------+
| table_schema | table_name |
+--------------+-------------+
| mydb | ApprovePost |
+--------------+-------------+
1 row in set (0.00 sec)
Looks like you need to use the FLUSH TABLES command for the INFORMATION_SCHEMA.TABLES to reflect existing tables.
Reference:
TABLE CACHE
Hmmm...
Are results stable? May be some pending transaction..
What is shown by
show tables like '%'
Also it may be an issue with physical files.
Is folder for mydb exists?