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_name
s whose column_name
s do not match in the two database versions?
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;