Consulta para comparar la estructura de dos tablas en MySQL

18

Para automatizar el proceso de copia de seguridad de una de mis bases de datos MySQL, me gustaría comparar la estructura de dos tablas (versión actual frente a versión anterior).

¿Se te ocurre una consulta que pueda comparar dos tablas?

Aquí hay algunas tablas de ejemplo que puede comparar.

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)
);

Las dos primeras tablas tienen estructuras idénticas. El último es diferente. Solo necesito saber si dos tablas tienen estructuras diferentes o no. No estoy interesado en cómo difieren.

sjdh
fuente
@ yagmoth555 suponiendo que mi pregunta sea lo suficientemente sobre el tema para SF, si tiene ganas de escribir una respuesta similar aquí, la aceptaré. de lo contrario, responderé mi propia pregunta más tarde hoy.
No estoy seguro de si encaja allí, pero escribiré una respuesta, ya que de todos modos puede encajar allí, ya que de todos modos puede ser una pregunta de administrador del servidor :) Como, si respondiera con todo un volcado de la estructura de la tabla, y un grep entre los dos, habría encajado. En mi opinión
1
Esto es imposible de hacer de manera confiable. No todos los cambios en la estructura de datos entre revisiones de software se manifiestan realmente como cambios en el esquema. Solo los desarrolladores de la aplicación saben exactamente qué ha cambiado. Si los desarrolladores no le han proporcionado una herramienta oficial para la migración, debe preguntarles cómo migrar entre versiones específicas de la aplicación.
kasperd
1
Creé una herramienta gratuita que generará las declaraciones alter para hacer que la segunda tabla sea la misma que la primera tablediff.com . Aún alfa.
Mihai

Respuestas:

34

DOS TABLAS EN LA BASE DE DATOS ACTUAL

Si desea saber si dos tablas son diferentes, ejecute esto

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;

Si realmente necesita ver las diferencias, ejecute esto

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;

DOS TABLAS EN UNA BASE DE DATOS ESPECÍFICA

Si desea saber si dos tablas son diferentes en la base de datos mydb, ejecute esto

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;

Si realmente necesita ver las diferencias, ejecute esto

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;

DOS TABLAS EN DOS BASES DE DATOS DIFERENTES

Si quieres saber si db1.tb1y db2.tb2son diferentes, ejecuta esto

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;

Si realmente necesita ver las diferencias, ejecute esto

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;

DARLE UNA OPORTUNIDAD !!!

RolandoMySQLDBA
fuente
Tuve que hacer una comparación lado a lado de dos bases de datos de desarrollo que tienen todas las mismas tablas en diferentes estados, pude modificar esto para cumplir ese objetivo muy bien.
Jason
1
@Jason me alegro de poder ayudar !!!
RolandoMySQLDBA
Muy útil, me ahorró un tiempo precioso
Nikita Kurtin
cómo mostrar el nombre del esquema, el nombre de la tabla en columnas seleccionadas
iCoders
2

Puede comparar la suma de comprobación de salida de 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  -
akuzminsky
fuente
1
Si hay un AUTO_INCREMENTO, podría interponerlo.
RolandoMySQLDBA
Bien, entonces cortas el valor de
autoincremento
Ahora, eso es rápido y sucio. +1 !!!
RolandoMySQLDBA
Esta parece una solución inteligente si está trabajando desde el shell. Gracias.
sjdh
2
No hay garantía de que las columnas estén en el mismo orden, por lo que esquemas idénticos específicos pueden producir sumas de verificación diferentes.
Zds
1

Ampliando la respuesta de RolandoMySQLDBA:

Para ver también el nombre de la tabla, consulte esto:

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;
Bibek Lekhak
fuente
0

Eche un vistazo a la tabla de columnas en el esquema de información: el campo tipo_columna. Eso le permitirá comparar estructuras de tablas.

Vérace
fuente
0

Mi mejor manera de comparar 2 bases de datos (DB1, DB2): solo tablas / vistas, restricciones y claves externas no están incluidas. En mi caso, siempre uso el siguiente SQL para comparar PRODUCTION con UAT o UAT con DEV.

DB DIFF (comparar tablas / vistas)

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;
JKar
fuente
-2

para todos los cambios en la estructura de tablas de dos bases de datos:

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;

Ref .: de RolandoMySQLDBA ans

murtaza.webdev
fuente
¿Qué es esto exactamente? ¿Una mejora en la respuesta de Rolando?
ypercubeᵀᴹ
no mejorado pero para ver cambios directos en todas las tablas entre dos bases de datos.
murtaza.webdev