Consulta para comparar a estrutura de duas tabelas no MySQL


18

Para automatizar o processo de backup de um dos meus bancos de dados MySQL, eu gostaria de comparar a estrutura de duas tabelas (versão atual versus versão antiga).

Você consegue pensar em uma consulta que possa comparar duas tabelas?

Aqui estão alguns exemplos de tabelas que você pode 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)
);

As duas primeiras tabelas têm estruturas idênticas. O último é diferente. Eu só preciso saber se duas tabelas têm estruturas diferentes ou não. Não estou interessado em saber como eles diferem.


@ yagmoth555, supondo que minha pergunta esteja no tópico o suficiente para SF, se você quiser digitar uma resposta semelhante aqui, eu a aceito. caso contrário, responderei à minha própria pergunta ainda hoje.

Não tenho certeza se ele cabe lá, mas vou escrever uma resposta, pois pode caber de qualquer maneira, pois pode ser uma pergunta de administrador do servidor :) Como se eu respondesse com todo um despejo da estrutura da tabela, e um grep entre os dois, caberia. É uma linha cinza na minha opinião

11
Isso é impossível de ser feito de maneira confiável. Nem todas as alterações na estrutura dos dados entre as revisões de software realmente se manifestam como alterações no esquema. Somente os desenvolvedores do aplicativo sabem exatamente o que mudou. Se os desenvolvedores não fornecerem uma ferramenta oficial para a migração, você precisará perguntar a eles como migrar entre versões específicas do aplicativo.
kasperd

11
Eu criei uma ferramenta gratuita que irá gerar as instruções alter para tornar a segunda tabela igual à primeira tablediff.com . Ainda alfa.
Mihai

Respostas:


34

DUAS MESAS NA BASE DE DADOS ATUAL

Se você quiser saber se duas tabelas são diferentes, execute este

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 você realmente precisa ver as diferenças, execute este

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;

DUAS MESAS EM UMA BASE DE DADOS ESPECÍFICA

Se você quiser saber se duas tabelas são diferentes no banco de dados mydb, execute este

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 você realmente precisa ver as diferenças, execute este

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;

DUAS MESAS EM DUAS BASES DE DADOS DIFERENTES

Se você quiser saber se db1.tb1e db2.tb2é diferente, execute este

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 você realmente precisa ver as diferenças, execute este

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;

DE UMA CHANCE !!!


Eu precisava fazer uma comparação lado a lado de dois bancos de dados dev que possuíssem as mesmas tabelas em diferentes estados. Consegui modificá-lo para atingir esse objetivo.
Jason

11
@ Jason feliz que eu poderia ajudar !!!
RolandoMySQLDBA

Muito útil, me salvou um tempo precioso
Nikita Kurtin

como mostrar nome do esquema, nome de tabela em alguns colunas
iCoders

2

Você pode comparar a soma de verificação da saída do 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  -

11
Se houver um AUTO_INCREMENT, ele pode atrapalhar.
RolandoMySQLDBA

Certo, então você reduzir o valor autoincrement
akuzminsky

Agora, isso é rápido e sujo. +1 !!!
RolandoMySQLDBA

Essa parece uma solução inteligente se você estiver trabalhando com o shell. Obrigado.
Sjdh

2
Não há garantia de que as colunas estejam na mesma ordem; portanto, esquemas idênticos em termos específicos podem produzir somas de verificação diferentes.
Zds 29/05

1

Expandindo a resposta de RolandoMySQLDBA:

Para ver também o nome da tabela, consulte:

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

Dê uma olhada na tabela de colunas no campo information_schema - o column_type. Isso permitirá comparar estruturas da tabela.


0

Minha melhor maneira de comparar dois bancos de dados (DB1, DB2) - apenas tabelas / visualizações, restrições e chave estrangeira não está incluída. No meu caso, eu sempre uso o SQL a seguir para comparar PRODUCTION com UAT ou UAT com DEV.

DB DIFF (compare tabelas / visualizações)

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

para todas as alterações na estrutura da tabela de dois bancos de dados:

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


O que exatamente é isso? Uma melhoria na resposta de Rolando?
precisa saber é o seguinte

não foi aprimorado, mas para exibir alterações diretas em todas as tabelas entre dois bancos de dados.
Murtaza.webdev 18/01/16
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.