Requête pour comparer la structure de deux tables dans MySQL


18

Pour automatiser le processus de sauvegarde d'une de mes bases de données MySQL, je voudrais comparer la structure de deux tables (version actuelle vs ancienne version).

Pouvez-vous penser à une requête qui peut comparer deux tableaux?

Voici quelques exemples de tableaux que vous pouvez comparer.

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

Les deux premiers tableaux ont des structures identiques. Le dernier est différent. J'ai juste besoin de savoir si deux tables ont des structures différentes ou non. Je ne suis pas intéressé par la façon dont ils diffèrent.


@ yagmoth555 en supposant que ma question est assez sur le sujet pour SF, si vous avez envie de taper une réponse similaire ici, je l'accepterai. sinon, je répondrai à ma propre question plus tard dans la journée.

Je ne sais pas si cela convient, mais j'écrirai une réponse, car elle peut s'y adapter de toute façon, car il peut s'agir d'une question d'administration du serveur de toute façon :) Comme, si je répondais avec todo un vidage de la structure de la table, et une grep entre les deux, ça aurait pu convenir. C'est une ligne grise à mon avis

1
C'est impossible à faire de manière fiable. Toutes les modifications de la structure des données entre les révisions logicielles ne se manifestent pas réellement comme des changements dans le schéma. Seuls les développeurs de l'application savent exactement ce qui a changé. Si les développeurs ne vous ont pas fourni d'outil officiel de migration, vous devez leur demander comment migrer entre des versions spécifiques de l'application.
kasperd

1
J'ai créé un outil gratuit qui générera les instructions alter pour rendre le deuxième tableau identique au premier tablediff.com . Toujours alpha.
Mihai

Réponses:


34

DEUX TABLEAUX DANS LA BASE DE DONNÉES ACTUELLE

Si vous voulez savoir si deux tables sont différentes, exécutez cette

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 vous avez réellement besoin de voir les différences, exécutez cette

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;

DEUX TABLEAUX DANS UNE BASE DE DONNÉES SPÉCIFIQUE

Si vous voulez savoir si deux tables sont différentes dans la base de données mydb, exécutez cette

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 vous avez réellement besoin de voir les différences, exécutez cette

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;

DEUX TABLEAUX DANS DEUX BASES DE DONNÉES DIFFÉRENTES

Si vous voulez savoir si db1.tb1et db2.tb2sont différents, exécutez ceci

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 vous avez réellement besoin de voir les différences, exécutez cette

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;

ESSAIE !!!


J'avais besoin de faire une comparaison côte à côte de deux bases de données de développement qui ont toutes les mêmes tables dans des états différents, j'ai pu le modifier pour atteindre cet objectif.
Jason

1
@Jason heureux d'avoir pu aider !!!
RolandoMySQLDBA

Très utile, m'a fait gagner un temps précieux
Nikita Kurtin

comment afficher le nom du schéma, le nom de la table dans certaines colonnes
iCoders

2

Vous pouvez comparer la somme de contrôle de la sortie 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  -

1
S'il y a un AUTO_INCREMENT, il pourrait le gêner.
RolandoMySQLDBA du

À droite, alors vous coupez la valeur d'auto-incrémentation
akuzminsky

Maintenant, c'est rapide et sale. +1 !!!
RolandoMySQLDBA

Cela semble une solution intelligente si vous travaillez à partir du shell. Je vous remercie.
sjdh

2
Il n'y a aucune garantie que les colonnes seront dans le même ordre, donc des schémas identiques selon les spécifications peuvent produire des sommes de contrôle différentes.
Zds

1

Extension de la réponse de RolandoMySQLDBA:

Pour voir également le nom de la table, interrogez ceci:

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

Jetez un œil à la table des colonnes dans le champ information_schema - le champ column_type. Cela vous permettra de comparer les structures de table.


0

Ma façon ultime de comparer 2 bases de données (DB1, DB2) - les tables / vues uniquement, les contraintes et la clé étrangère ne sont pas incluses. Dans mon cas, j'utilise toujours SQL suivant pour comparer la PRODUCTION avec UAT ou UAT avec DEV.

DB DIFF (comparer les tableaux / vues)

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

pour tous les changements dans la structure des tables de deux bases de données:

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;

Réf .: de RolandoMySQLDBA ans


Qu'est-ce que c'est exactement? Une amélioration de la réponse de Rolando?
ypercubeᵀᴹ

pas amélioré mais pour afficher les changements directs dans toutes les tables entre deux bases de données.
murtaza.webdev
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.