MYSQL - copy tables with specific prefix between databases - mysql

Is there a SQL command to copy many tables with specific prefix (ie yot_) between two MYSQL databases? The DB user has access to both of the DB

There's no SQL statement of any kind that operates on tables using wildcards. You must name tables explicitly.
You can, however, generate the statements by querying the INFORMATION_SCHEMA:
SELECT CONCAT(
'RENAME TABLE my_old_schema.`', TABLE_NAME, '` '
' TO my_new_schema.`', TABLE_NAME, '`;'
) AS _stmt
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'yot\_%'
AND TABLE_SCHEMA='my_old_schema';
That's an example of generating a series of RENAME TABLE statements, which will move the tables from one schema to another. But it demonstrates the technique
You can try to make table-copy instead of move, with CREATE TABLE new_table LIKE old_table; followed by INSERT INTO new_table SELECT * FROM old_table;

Related

MariaDB set row_format to dynamic to all tables in one command

i want to change the row_format to dynamic on all tables in my database. When the datebase is selected i could do "ALTER TABLE tablename ROW_FORMAT=DYNAMIC;" to do it manually. Unfortunately there are around 100 tables to be changed.
How can i change the row format to dynamic on every tables in a specific DB that has something different to DYNAMIC?
I've been trying it but i cant find a working solution.
You can't ALTER TABLE more than one table at a time, but you can generate all the necessary ALTER TABLE statements this way:
SELECT CONCAT(
'ALTER TABLE `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` ',
'ROW_FORMAT=DYNAMIC;'
) AS _alter
FROM INFORMATION_SCHEMA.TABLES
WHERE ENGINE='InnoDB' AND ROW_FORMAT <> 'DYNAMIC';
Capture the output of that and run it as an SQL script.

Dropping all schemas with no tables

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)

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 to assume a table prefix on a entire MySQL script?

I have a script to run in my database.
But the problem is this script assume the tables have no prefix on it and all databases have a prefix (let call it prefix_).
Is there a command or a way to MySQL try to run
INSERT INTO prefix_mytable ...
instead of
INSERT INTO mytable...
for all of sql queries at the script (UPDATE, INSERT and DELETE)?
There is no way in MySQL to automatically prefix tables in the way you're describing. #MichaelBerkowski is correct.
The best I can suggest is that you create a second database with updateable views, using unprefixed names, as front-ends to your prefixed table names.
Here's an example:
mysql> CREATE DATABASE test;
mysql> CREATE TABLE test.prefix_mytable (id INT PRIMARY KEY, x VARCHAR(20));
mysql> CREATE DATABASE test2;
mysql> CREATE VIEW test2.mytable AS SELECT * FROM test.prefix_mytable;
Now you can insert using the unprefixed names:
mysql> INSERT INTO test2.mytable (id, x) VALUES (123, 'abc');
And to verify that the data was inserted into your original table:
mysql> SELECT * FROM test.prefix_mytable;
Once you do that, you can run your SQL script against database test2 and all the INSERTs should get to your original tables all right.
If you have a lot of tables you need to create views for, you can automate the creation of the CREATE VIEW statements:
mysql> SELECT CONCAT('CREATE VIEW test2.', REPLACE(TABLE_NAME, 'prefix_', ''),
' AS SELECT * FROM test.', TABLE_NAME, ';') AS _sql
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME LIKE 'prefix\_%';
Here is the guide to replace WordPress table prefix from wp_ to a different, like this you can update any mysql table. How to rename WordPress tables prefix?