Zapytanie w celu porównania struktury dwóch tabel w MySQL

18

Aby zautomatyzować proces tworzenia kopii zapasowej jednej z moich baz danych MySQL, chciałbym porównać strukturę dwóch tabel (bieżąca wersja ze starą wersją).

Czy potrafisz wymyślić zapytanie, które może porównać dwie tabele?

Oto kilka przykładowych tabel, które możesz porównać.

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

Pierwsze dwie tabele mają identyczne struktury. Ostatni jest inny. Muszę tylko wiedzieć, czy dwie tabele mają różne struktury, czy nie. Nie interesuje mnie ich różnica.

sjdh
źródło
@ yagmoth555, zakładając, że moje pytanie jest wystarczająco tematyczne dla SF, jeśli masz ochotę wpisać podobną odpowiedź tutaj, zaakceptuję ją. w przeciwnym razie dzisiaj odpowiem na własne pytanie.
Nie jestem pewien, czy to tam pasuje, ale napiszę odpowiedź, ponieważ i tak może się tam zmieścić, ponieważ może to być pytanie administratora serwera :) Jakbym, jeśli chciałbym odpowiedzieć todo zrzutem struktury tabeli, i grep między nimi, pasowałby. Moim zdaniem jest to szara linia
1
Nie da się tego zrobić niezawodnie. Nie wszystkie zmiany w strukturze danych między wersjami oprogramowania faktycznie objawiają się jako zmiany w schemacie. Tylko twórcy aplikacji wiedzą, co dokładnie się zmieniło. Jeśli programiści nie udostępnili Ci oficjalnego narzędzia do migracji, musisz zapytać ich, jak przeprowadzić migrację między konkretnymi wersjami aplikacji.
kasperd
1
Zrobiłem bezpłatne narzędzie, które wygeneruje instrukcje alter, aby druga tabela była taka sama jak pierwsza tablediff.com . Wciąż alfa.
Mihai

Odpowiedzi:

34

DWA STOŁY W BIEŻĄCEJ BAZY DANYCH

Jeśli chcesz wiedzieć, czy dwie tabele są różne, uruchom to

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;

Jeśli naprawdę potrzebujesz zobaczyć różnice, uruchom to

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;

DWA STOŁY W SZCZEGÓLNEJ BAZIE DANYCH

Jeśli chcesz wiedzieć, czy dwie tabele różnią się w bazie danych mydb, uruchom to

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;

Jeśli naprawdę potrzebujesz zobaczyć różnice, uruchom to

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;

DWA STOŁY W DWÓCH RÓŻNYCH BAZACH DANYCH

Jeśli chcesz wiedzieć, czy db1.tb1i db2.tb2jesteś inny, uruchom to

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;

Jeśli naprawdę potrzebujesz zobaczyć różnice, uruchom to

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;

SPRÓBUJ !!!

RolandoMySQLDBA
źródło
Musiałem dokonać porównania dwóch baz danych deweloperów, które mają te same tabele w różnych stanach, byłem w stanie to zmodyfikować, aby ładnie osiągnąć ten cel.
Jason
1
@Jason cieszę się, że mogłem pomóc !!!
RolandoMySQLDBA
Bardzo pomocny, oszczędził mi cenny czas
Nikita Kurtin
jak wyświetlić nazwę schematu, nazwę tabeli w wybranych kolumnach
iCoders
2

Możesz porównać sumę kontrolną danych wyjściowych 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
źródło
1
Jeśli istnieje AUTO_INCREMENT, może to przeszkodzić.
RolandoMySQLDBA
Racja, a następnie
obniżysz
To jest szybkie i brudne. +1 !!!
RolandoMySQLDBA
To wydaje się sprytnym rozwiązaniem, jeśli pracujesz z powłoki. Dziękuję Ci.
sjdh
2
Nie ma gwarancji, że kolumny będą w tej samej kolejności, więc identyczne schematy mogą generować różne sumy kontrolne.
Zds
1

Rozwijając odpowiedź RolandoMySQLDBA:

Aby zobaczyć również nazwę tabeli, zapytaj:

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
źródło
0

Spójrz na tabelę kolumn w schemacie_informacyjnym - pole typ_kolumny. To pozwoli ci porównać struktury tabel.

Vérace
źródło
0

Mój najlepszy sposób porównywania 2 baz danych (DB1, DB2) - tylko tabele / widoki, ograniczenia i klucz obcy nie są uwzględnione. W moim przypadku zawsze używam następującego SQL do porównania PRODUKCJI z UAT lub UAT z DEV.

DB DIFF (porównaj tabele / widoki)

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
źródło
-2

dla wszystkich zmian w strukturze tabeli dwóch baz danych:

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 .: od RolandoMySQLDBA ans

murtaza.webdev
źródło
Co to dokładnie jest? Poprawa odpowiedzi Rolando?
ypercubeᵀᴹ
nie poprawiono, ale aby wyświetlić bezpośrednie zmiany we wszystkich tabelach między dwiema bazami danych.
murtaza.webdev