1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQLiteでデータベース間の比較がしたい

Last updated at Posted at 2023-04-02

はじめに

恒例のお断りですが、この文章の内容は、筆者が所属している会社・団体とは一切関わりがありません。いわゆる「自主的な研究の成果の発表」というものです。

「泣きたくなるほど遅い」などの困難を乗り越えてSQLiteで簡単にデータベースが作成できることが分かると、調子に乗ってついついデータベースを作りすぎてしまうことってあると思います。(そんなわけ、ねーだろ!と思ったあなた、大人ですね。)で、しばらくして我に返って、「先程作ったデータベースと今作ったデータベース、実は中身は同じなのでは」と思った時、「ん?データベースが異なる場合に、どうやって比較するのかな。同じデータベースの中ならSQLで何とかできそうだけど、、、」と思ってしまったら、この先を読んでください。

sqldiff.exe

データベースと言ったってどうせファイルだろ、とdiffを使うと

$ diff my_sqlite1.db my_sqlite2.db 
Binary files my_sqlite1.db and my_sqlite2.db differ

(違うことは分かるが何が違うのかは全く分からない)という残念な結果になります。(実はここでmy_sqlite1.dbとmy_sqlite2.dbは(見た目には)同じデータが入っている入っているはずなのです。きっとメタデータか何かが異なるのでしょうね。)

ここでSQLにこだわって、「dumpしたもの同士を比較するのか」とか考え始めると茨の道かもです。

やはり、データベース同士を簡単に比較したいという需要はあるようで、SQLiteのサイトにsqldiff.exeなんてものがあります。

.exeなんて書いてあるから、Windows専用のツールなのではと思うかもしれませんが、SQLite3をインストールした私のPC(FreeBSD/GhostBSD)にも入ってました(もちろん.exeなんてついていませんが)1。SQLite3をインストールするとついてくるみたいですね。

$ pkg which `which sqldiff`
/usr/local/bin/sqldiff was installed by package sqlite3-3.41.0,1

中身が同じ(だけどファイルは異なる)データベースを比較すると以下のようになります。

$ sqldiff my_sqlite1.db my_sqlite2.db

sqldiffはmy_sqlite1.dbをmy_sqlite2.dbと同じにするためのSQLコマンド(群)を出力するもののようですから、何も出ない=>同じにするためにSQLコマンドは必要ない=>2つのデータベースの中身は同じ、ということになるようです。
が、diffの-sオプションみたいに

$ diff -s file1 file2 
Files file1 and file2 are identical

とずばっと言ってくれるともっと安心ですよね。sqldiffには残念ながらdiffの-sオプションに相当するものはなさそうです。そのかわりに以下のようにすれば多少は安心できるのではないでしょうか。

--summary

$ sqldiff --summary my_sqlite1.db my_sqlite2.db
my_table0: 0 changes, 0 inserts, 0 deletes, 1085 unchanged
my_table1: 0 changes, 0 inserts, 0 deletes, 1066 unchanged
my_table2: 0 changes, 0 inserts, 0 deletes, 1593 unchanged
my_table3: 0 changes, 0 inserts, 0 deletes, 327 unchanged

このオプションは差の集計を出力してくれるものです。上の例で言うと、どちらのデータベースにも共通の名前のテーブルが(4つ)あり、各テーブルで変更されたもの(change)、挿入されたもの(insert)、削除されたもの(delete)はなく、変化がないもの(unchanged)ばかりだ、ということが分かります。なので、my_sqlite1.dbとmy_sqlite2.dbの中身は同じだと自信を持って判断できますね。

--transaction

sqldiff --transaction my_sqlite1.db my_sqlite2.db 
BEGIN TRANSACTION;
COMMIT;

このオプションは出力をトランザクションとしてまとめてくれるものです。"BEGIN TRANSACTION;"と"COMMIT;"で囲まれた部分が出力ですから、出力は何もない、ただし、"BEGIN TRANSACTION;"と"COMMIT;"は出力しているからsqldiffとしてはちゃんと動作しているようだ、と安心できるのではないでしょうか。

  1. MacにもHomebrewで入れられます。ただし、SQLite3をインストールするとついてくるというわけではなく、sqldiffを独立にインストールするようです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?