MySQLの2つのテーブルの構造を比較するクエリ


18

MySQLデータベースの1つのバックアッププロセスを自動化するために、2つのテーブルの構造(現在のバージョンと古いバージョン)を比較したいと思います。

2つのテーブルを比較できるクエリを考えられますか?

比較できる表の例を次に示します。

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

最初の2つのテーブルの構造は同じです。最後のものは異なります。2つのテーブルの構造が異なるかどうかを知る必要があるだけです。私はそれらがどのように異なるかに興味がありません。


@ yagmoth555は私の質問がSFにとって十分に話題になっていると仮定して、ここで同様の答えを入力したいなら、それを受け入れます。それ以外の場合は、本日後半に自分の質問に答えます。

それがそこに収まるかどうかはわかりませんが、どうにか収まるので、サーバー管理者の質問になる可能性があるため、答えを書きます:)テーブル構造のダンプをtodoで答えると、 2つの間にgrepがあれば、それはぴったりだったでしょう。私自身の意見では灰色の線です

1
これを確実に行うことは不可能です。ソフトウェアリビジョン間のデータ構造のすべての変更が、実際にはスキーマの変更として現れるわけではありません。アプリケーションの開発者のみが、何が変更されたかを正確に知っています。開発者が移行用の公式ツールを提供していない場合は、アプリケーションの特定のバージョン間での移行方法を尋ねる必要があります。
カスペルド

1
alter文を生成して2番目のテーブルを最初のtablediff.comと同じにする無料のツールを作成しました。まだアルファ。
ミハイ

回答:


34

現在のデータベースの2つのテーブル

2つのテーブルが異なるかどうかを知りたい場合は、これを実行します

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;

実際に違いを確認する必要がある場合は、これを実行してください

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;

特定のデータベースの2つのテーブル

データベースmydbで2つのテーブルが異なるかどうかを知りたい場合は、これを実行します

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;

実際に違いを確認する必要がある場合は、これを実行してください

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;

2つの異なるデータベースの2つのテーブル

あなたがあれば知りたい場合db1.tb1db2.tb2異なり、これを実行します

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;

実際に違いを確認する必要がある場合は、これを実行してください

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;

試してみる !!!


すべてのテーブルが異なる状態にある2つのdevデータベースを並べて比較する必要がありましたが、この目標をうまく達成するためにこれを変更することができました。
ジェイソン

1
@ジェイソンは私が助けることができてうれしい!!!
-RolandoMySQLDBA

とても助かりました。貴重な時間を節約してくれました
ニキータ・カーティン

選択列にスキーマ名、テーブル名を表示する方法
iCoders

2

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
AUTO_INCREMENTがある場合、それが邪魔になる可能性があります。
RolandoMySQLDBA 14

右、あなたは自動インクリメント値カット
akuzminsky

今、それは迅速で汚れています。+1 !!!
RolandoMySQLDBA 14

シェルから作業している場合、これは賢い解決策のようです。ありがとうございました。
sjdh 14

2
列の順序が同じであるという保証はないため、仕様に関して同一のスキーマは異なるチェックサムを生成できます。
Zds

1

RolandoMySQLDBAの答えを拡大:

テーブル名も表示するには、次のクエリを実行します。

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

information_schema-column_typeフィールドの列テーブルを見てください。これにより、テーブル構造を比較できます。


0

2つのデータベース(DB1、DB2)を比較する私の究極の方法-テーブル/ビューのみ、制約、および外部キーは含まれません。私の場合、次のSQLを常に使用して、PRODUCTIONとUATまたはUATとDEVを比較します。

DB DIFF(テーブル/ビューの比較)

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

2つのデータベースのテーブル構造のすべての変更について:

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;

参照:RolandoMySQLDBA ansから


これは正確に何ですか?Rolandoの回答の改善?
ypercubeᵀᴹ

改善されていませんが、2つのデータベース間のすべてのテーブルの直接的な変更を表示します。
murtaza.webdev
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.