Interrogazione per confrontare la struttura di due tabelle in MySQL


18

Per automatizzare il processo di backup di uno dei miei database MySQL, vorrei confrontare la struttura di due tabelle (versione corrente vs vecchia versione).

Riesci a pensare a una query in grado di confrontare due tabelle?

Ecco alcune tabelle di esempio che puoi confrontare.

CREATE TABLE product_today
(
  pname VARCHAR(150),
  price int,
  PRIMARY KEY (pname)
);

CREATE TABLE product_yesterday
(
  pname VARCHAR(150),
  price int,
  PRIMARY KEY (pname)
);

CREATE TABLE product_2days_back
(
  pname VARCHAR(15),
  price int,
  PRIMARY KEY (pname)
);

Le prime due tabelle hanno strutture identiche. L'ultimo è diverso. Devo solo sapere se due tabelle hanno strutture diverse o meno. Non mi interessa il modo in cui differiscono.


@ yagmoth555 supponendo che la mia domanda sia abbastanza in argomento per SF, se hai voglia di scrivere una risposta simile qui accetterò. altrimenti, risponderò alla mia domanda più tardi oggi.

Non sono sicuro se si adatta lì, ma scriverò una risposta, in quanto può adattarsi comunque lì, in quanto può essere comunque una domanda dell'amministratore del server :) Come, se rispondessi con un dump della struttura della tabella, e un grep tra i due, si sarebbe adattato. È una linea grigia secondo me

1
Questo è impossibile da fare in modo affidabile. Non tutte le modifiche alla struttura dei dati tra le revisioni del software si manifestano effettivamente come cambiamenti nello schema. Solo gli sviluppatori dell'applicazione sanno esattamente cosa è cambiato. Se gli sviluppatori non ti hanno fornito uno strumento ufficiale per la migrazione, devi chiedere loro come migrare tra versioni specifiche dell'applicazione.
Kasperd,

1
Ho creato uno strumento gratuito che genererà le istruzioni alter per rendere la seconda tabella uguale alla prima tablediff.com . Ancora alfa.
Mihai,

Risposte:


34

DUE TABELLE NEL DATABASE ATTUALE

Se vuoi sapere se due tabelle sono diverse, esegui questo

SELECT IF(COUNT(1)>0,'Differences','No Differences') Comparison FROM
(
    SELECT
        column_name,ordinal_position,
        data_type,column_type,COUNT(1) rowcount
    FROM information_schema.columns
    WHERE table_schema=DATABASE()
    AND table_name IN ('product_today','product_yesterday')
    GROUP BY
        column_name,ordinal_position,
        data_type,column_type
    HAVING COUNT(1)=1
) A;

Se hai effettivamente bisogno di vedere le differenze, esegui questo

SELECT column_name,ordinal_position,data_type,column_type FROM
(
    SELECT
        column_name,ordinal_position,
        data_type,column_type,COUNT(1) rowcount
    FROM information_schema.columns
    WHERE table_schema=DATABASE()
    AND table_name IN ('product_today','product_yesterday')
    GROUP BY
        column_name,ordinal_position,
        data_type,column_type
    HAVING COUNT(1)=1
) A;

DUE TABELLE IN UN DATABASE SPECIFICO

Se vuoi sapere se due tabelle sono diverse nel database mydb, esegui questo

SELECT IF(COUNT(1)>0,'Differences','No Differences') Comparison FROM
(
    SELECT
        column_name,ordinal_position,
        data_type,column_type,COUNT(1) rowcount
    FROM information_schema.columns
    WHERE table_schema='mydb'
    AND table_name IN ('product_today','product_yesterday')
    GROUP BY
        column_name,ordinal_position,
        data_type,column_type
    HAVING COUNT(1)=1
) A;

Se hai effettivamente bisogno di vedere le differenze, esegui questo

SELECT column_name,ordinal_position,data_type,column_type FROM
(
    SELECT
        column_name,ordinal_position,
        data_type,column_type,COUNT(1) rowcount
    FROM information_schema.columns
    WHERE table_schema='mydb'
    AND table_name IN ('product_today','product_yesterday')
    GROUP BY
        column_name,ordinal_position,
        data_type,column_type
    HAVING COUNT(1)=1
) A;

DUE TABELLE IN DUE DIVERSI DATABASI

Se vuoi sapere se db1.tb1e db2.tb2sono diversi, esegui questo

SELECT IF(COUNT(1)>0,'Differences','No Differences') Comparison FROM
(
    SELECT
        column_name,ordinal_position,
        data_type,column_type,COUNT(1) rowcount
    FROM information_schema.columns
    WHERE
    (
        (table_schema='db1' AND table_name='tb1') OR
        (table_schema='db2' AND table_name='tb2')
    )
    AND table_name IN ('product_today','product_yesterday')
    GROUP BY
        column_name,ordinal_position,
        data_type,column_type
    HAVING COUNT(1)=1
) A;

Se hai effettivamente bisogno di vedere le differenze, esegui questo

SELECT column_name,ordinal_position,data_type,column_type FROM
(
    SELECT
        column_name,ordinal_position,
        data_type,column_type,COUNT(1) rowcount
    FROM information_schema.columns
    WHERE
    (
        (table_schema='db1' AND table_name='tb1') OR
        (table_schema='db2' AND table_name='tb2')
    )
    AND table_name IN ('product_today','product_yesterday')
    GROUP BY
        column_name,ordinal_position,
        data_type,column_type
    HAVING COUNT(1)=1
) A;

PROVACI !!!


Avevo bisogno di fare un confronto fianco a fianco tra due database di sviluppo che hanno tutte le stesse tabelle in stati diversi, sono stato in grado di modificarlo per raggiungere quell'obiettivo in modo piacevole.
Jason,

1
@Jason felice di poterti aiutare !!!
RolandoMySQLDBA

Molto utile, mi ha fatto risparmiare un po 'di tempo prezioso
Nikita Kurtin

come mostrare il nome dello schema, il nome della tabella nelle colonne selezionate
iCoders

2

È possibile confrontare il checksum dell'output di SHOW CREATE TABLE product_today

# mysql -NBe "SHOW CREATE TABLE sakila.actor"| sed -r 's/AUTO_INCREMENT=[0-9]+/AUTO_INCREMENT=XXX/g' | md5sum
# 1bc0d72b294d1a93ce01b9a2331111cc  -

1
Se esiste un AUTO_INCREMENT, potrebbe metterlo in mezzo.
RolandoMySQLDBA,

Bene, allora hai tagliato il valore di
incremento automatico

Ora, è veloce e sporco. +1 !!!
RolandoMySQLDBA

Questa sembra una soluzione intelligente se stai lavorando dalla shell. Grazie.
sjdh,

2
Non vi è alcuna garanzia che le colonne siano nello stesso ordine, quindi schemi identici specifici possono produrre checksum diversi.
Zds,

1

Espandendo la risposta di RolandoMySQLDBA:

Per vedere anche il nome della tabella, interroga questo:

SELECT table_name, column_name,ordinal_position,data_type,column_type FROM
(
    SELECT
        table_name, column_name,ordinal_position,
        data_type,column_type,COUNT(1) rowcount
    FROM information_schema.columns
    WHERE table_schema=DATABASE()
    AND table_name IN ('table_1','table_2')
    GROUP BY
        column_name,ordinal_position,
        data_type,column_type
    HAVING COUNT(1)=1
) A;

0

Dai un'occhiata alla tabella delle colonne nel information_schema - il campo column_type. Ciò ti consentirà di confrontare le strutture delle tabelle.


0

Il mio ultimo modo di confrontare 2 database (DB1, DB2) - solo tabelle / viste, vincoli e chiave esterna non sono inclusi. Nel mio caso uso sempre il seguente SQL per confrontare PRODUCTION con UAT o UAT con DEV.

DB DIFF (confronta tabelle / viste)

select x.* from (
SELECT a.table_name, a.column_name,
    max(IF(b.TS='S1',b.ordinal_position,null)) as S1_ordinal_position,
    max(IF(b.TS='S2',b.ordinal_position,null)) as S2_ordinal_position,
    max(IF(b.TS='S1',b.data_type       ,null)) as S1_data_type,
    max(IF(b.TS='S2',b.data_type       ,null)) as S2_data_type,
    max(IF(b.TS='S1',b.column_type     ,null)) as S1_column_type,
    max(IF(b.TS='S2',b.column_type     ,null)) as S2_column_type
FROM
(SELECT DISTINCT table_name, column_name
 FROM information_schema.columns
 WHERE table_schema IN ('DB1','DB2')
) a
INNER JOIN
(SELECT IF(table_schema='DB1','S1','S2') as TS,
    table_schema,table_name,column_name,ordinal_position,data_type,column_type
 FROM information_schema.columns
 WHERE table_schema IN ('DB1','DB2')
) b
on (a.table_name = b.table_name and a.column_name = b.column_name)
group by a.table_name, a.column_name
) x
where x.S1_ordinal_position != x.S2_ordinal_position or x.S1_ordinal_position is null or x.S2_ordinal_position is null
or    x.S1_data_type        != x.S2_data_type
or    x.S1_column_type      != x.S2_column_type
ORDER BY x.table_name;

-2

per tutte le modifiche nella struttura della tabella di due database:

SELECT table_schema, table_name, column_name,ordinal_position,data_type,column_type FROM (
    SELECT
        table_schema, table_name, column_name,ordinal_position,
        data_type,column_type,COUNT(1) rowcount
    FROM information_schema.columns
    WHERE table_schema IN ('database1', 'database2')
    GROUP BY
        column_name,ordinal_position,
        data_type,column_type
    HAVING COUNT(1)=1 ) A;

Rif .: da RolandoMySQLDBA ans


Cos'è esattamente questo? Un miglioramento sulla risposta di Rolando?
ypercubeᵀᴹ

non migliorato ma per visualizzare le modifiche dirette in tutte le tabelle tra due database.
murtaza.webdev il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.