前書き
以前、「リプレース対応前後の旧システム・新システムにおいて、アウトプットテーブルの内容が完全一致するかどうか検証したい」といった機会がありました。
大量のテーブル & 大量のデータ を比較するので時間がかかる…
単純比較するだけ なのでそこまで手間をかけたくない…
という思いから、自動比較検証スクリプトを作成しました。どなたかのお役に立てれば幸いです。
この記事で紹介しているスクリプト
batファイルを実行するだけでデータの比較検証ができるスクリプトを作ります。
👇処理イメージは以下の通りです。
- A5M2cmdで、比較対象のデータを取得し、CSVファイルに出力する
- WinMergeコマンドで、出力したCSVファイルを比較する
- WinMerge比較結果をHTML形式のレポートに吐き出す
用意するもの
- WinMerge
- A5M2
- A5M2cmd
サンプルコード全量
<👇①実行対象のbat>
@echo off
rem フォルダ名やファイル名に使用するジョブ名を設定
set JOB_NAME=TEST
rem ログファイルのパス設定
set LOG_FOLDER=log
set yyyyMMdd=%date:/=%
set hhmmss=%time::=%
set hhmmss=%hhmmss:~0,6%
set hhmmss=%hhmmss: =0%
set logfile=%yyyyMMdd%\%LOG_FOLDER%\%JOB_NAME%_%yyyyMMdd%_%hhmmss%.log
rem エクスポートフォルダ設定
set NEW_CSV_FOLDER=%yyyyMMdd%\%JOB_NAME%_NEW
set OLD_CSV_FOLDER=%yyyyMMdd%\%JOB_NAME%_OLD
rem 比較結果フォルダ設定
set RESULT_FOLDER=%yyyyMMdd%\%JOB_NAME%_RESULT
rem 各種フォルダ作成
mkdir %yyyyMMdd%
mkdir %yyyyMMdd%\%LOG_FOLDER%
mkdir %NEW_CSV_FOLDER%
mkdir %OLD_CSV_FOLDER%
mkdir %RESULT_FOLDER%
rem 新旧のデータ取得
rem (補足)比較したいテーブル名をテキストファイルに列挙しておく
for /f "tokens=* delims=" %%i in (%JOB_NAME%_比較対象テーブル.txt) do (
@echo %%i
call 99_output_with_select.bat %%i | findstr "." >> "%logfile%"
)
rem CSVファイルを出力したフォルダを丸ごと比較検証(後続で比較検証バッチの実行結果(ERRORLEVEL)を取得するため、findstrコマンドは実行しない。 )
call 99_compare_new_and_old_folders.bat >> "%logfile%"
rem 標準出力されたERRORLEVELを取得
echo %ERRORLEVEL%
set RETURN_CODE=%ERRORLEVEL%
pause
rem エクスポートフォルダをzip圧縮
powershell compress-archive -Force %NEW_CSV_FOLDER%/* %NEW_CSV_FOLDER%.zip
powershell compress-archive -Force %OLD_CSV_FOLDER%/* %OLD_CSV_FOLDER%.zip
rem エクスポートフォルダを削除
rmdir /s /q %NEW_CSV_FOLDER%
rmdir /s /q %OLD_CSV_FOLDER%
exit /b %RETURN_CODE%
<👇②データ取得 & CSVファイル出力をする「99_output_with_select.bat」>
@echo off
rem 【説明】新・現行からSELECT文でデータを取得し、CSVファイルに出力する。
rem 【前提①】[NEW_SQL]フォルダに新システムから比較検証データを取得するSQL(テーブル名.sql)を作成しておくこと。
rem 【前提②】[OLD_SQL]フォルダに現行システムから比較検証データを取得するSQL(テーブル名.sql)を作成しておくこと。
rem DB接続文字列取得(NEW_CONNECTION/OLD_CONNECTION)
call connection_string.bat
@echo on
rem ---------------------------------------------------------------------------
rem 検証対象のテーブル名取得
set TARGET_TABLE=%1
rem SQL文格納先パス設定
set NEW_SQL_PATH=NEW_SQL\%TARGET_TABLE%.sql
set OLD_SQL_PATH=OLD_SQL\%TARGET_TABLE%.sql
rem 新システムのデータ取得
A5M2cmd "/Connect=%NEW_CONNECTION%" ^
/RunSQL ^
/FileName=%NEW_SQL_PATH% ^
/FilePattern=%NEW_CSV_FOLDER%\%TARGET_TABLE%.csv
rem 現行システムのデータ取得
A5M2cmd "/Connect=%OLD_CONNECTION%" ^
/RunSQL ^
/FileName=%OLD_SQL_PATH% ^
/FilePattern=%OLD_CSV_FOLDER%\%TARGET_TABLE%.csv
rem ---------------------------------------------------------------------------
@echo off
<👇上のbatで呼び出していた「connection_string.bat」>
rem ※ご自分のDB環境に合わせて記載を修正してください。
rem 新システムの接続文字列
set NEW_CONNECTION=__ConnectionType=Internal;ProviderName=SQL Server;ServerName=[サーバ名];Database=[データベース名];Authentication=OS;SavePassword=False;MaxDatabaseSize=128;MaxBufferSize=640;PacketSize=4096
rem 現行システムの接続文字列
set OLD_CONNECTION=__ConnectionType=Internal;ProviderName=Oracle;Direct=True;ServerName=[サーバ名];Port=[ポート番号];Database=[データベース名];SavePassword=False;UserName=[ユーザー名];Password=[パスワード]
<👇③WinMergeによる比較を行う「99_compare_new_and_old_folders.bat」>
@echo off
rem 【説明】WinMergeコマンドによりフォルダごと比較する。
rem 比較結果は[yyyymmdd/ジョブ名_RESULT/ジョブ名_フォルダ比較.html]に出力する。
@echo on
rem ---------------------------------------------------------------------------
rem WinMergeコマンドで新旧フォルダ比較
WinMergeU %NEW_CSV_FOLDER% %OLD_CSV_FOLDER% ^
/minimize ^
/noninteractive ^
/wl ^
/wr ^
/u ^
/ignorews ^
/enableexitcode ^
/cfg Settings/IgnoreSpace=2 ^
/cfg Settings/DirViewExpandSubdirs=1 ^
/cfg ReportFiles/ReportType=2 ^
/cfg ReportFiles/IncludeFileCmpReport=1 ^
/or "%RESULT_FOLDER%\%JOB_NAME%_フォルダ比較.html"
rem フォルダ比較結果を確認(0: 同一, 1: 差異あり, 2: エラー)
echo 比較結果:%ERRORLEVEL%
rem ---------------------------------------------------------------------------
@echo off
実行結果イメージ
①の、実行対象batをキックすると、以下のようなフォルダ構成でCSVファイル・HTMLレポートなどが出力されます。
[20250101](実行日)
┣ [JBXXX_RESULT](WinMerge比較結果)
┃ ┣ [JBXXX_フォルダ比較.files]
┃ ┗ [JBXXX_フォルダ比較.html]
┣ [log]
┃ ┗ [JBXXX_20250101_123456.log]
┣ [JBXXX_NEW.zip](比較対象データCSVファイルをzip圧縮したもの)
┗ [JBXXX_OLD.zip](同上)
解説
①実行対象batの解説
序盤はCSVファイルやWinMergeレポートファイルのファイル名や、出力先フォルダを設定・作成しているだけです。
@echo off
rem フォルダ名やファイル名に使用するジョブ名を設定
set JOB_NAME=TEST
(中略)
rem 各種フォルダ作成
mkdir %yyyyMMdd%
mkdir %yyyyMMdd%\%LOG_FOLDER%
mkdir %NEW_CSV_FOLDER%
mkdir %OLD_CSV_FOLDER%
mkdir %RESULT_FOLDER%
ここで、②の「99_output_with_select.bat」(データ取得bat)を呼び出しています。
「99_output_with_select.bat」の実行結果はログファイルへ出力するようにしています。
ちなみに、「比較対象テーブル.txt」に記載したテーブル名を「99_output_with_select.bat」に渡していますが、特にテーブル物理名である必要はありません。
(「99_output_with_select.bat」内では「引数.sql」を実行して「引数.csv」に出力する…みたいな処理をしているだけ)
rem 新旧のデータ取得
rem (補足)比較したいテーブル名をテキストファイルに列挙しておく
for /f "tokens=* delims=" %%i in (%JOB_NAME%_比較対象テーブル.txt) do (
@echo %%i
call 99_output_with_select.bat %%i | findstr "." >> "%logfile%"
)
ここで③の「99_compare_new_and_old_folders.bat」(データ比較bat)を呼び出しています。
こちらも「99_compare_new_and_old_folders.bat」の実行結果はログファイルへ出力するようにしています。
ちなみに、私はこのスクリプトをJP1より実行していました。
WinMergeの比較結果(0: 同一, 1: 差異あり, 2: エラー)に応じて、JP1のジョブを「正常終了・警告終了・異常終了」に遷移させたかったので、データ比較結果を「RETURN_CODE」に設定して返却するようにしています。
rem CSVファイルを出力したフォルダを丸ごと比較検証(後続で比較検証バッチの実行結果(ERRORLEVEL)を取得するため、findstrコマンドは実行しない。 )
call 99_compare_new_and_old_folders.bat >> "%logfile%"
rem 標準出力されたERRORLEVELを取得
echo %ERRORLEVEL%
set RETURN_CODE=%ERRORLEVEL%
pause
最後に、CSVファイルを格納したフォルダをzip圧縮 & 圧縮前のフォルダを削除しています。
データ量が膨大でCSVファイルが激重になってしまったのでこの処理を加えました。
rem エクスポートフォルダをzip圧縮
powershell compress-archive -Force %NEW_CSV_FOLDER%/* %NEW_CSV_FOLDER%.zip
powershell compress-archive -Force %OLD_CSV_FOLDER%/* %OLD_CSV_FOLDER%.zip
rem エクスポートフォルダを削除
rmdir /s /q %NEW_CSV_FOLDER%
rmdir /s /q %OLD_CSV_FOLDER%
exit /b %RETURN_CODE%
②データ取得bat(99_output_with_select.bat)の解説
記載した通りですが、「NEW_SQL」フォルダと「OLD_SQL」フォルダ内に予めSELECT文を記載したSQLファイルを作成しておく必要があります。
また、「connection_string.bat」で、A5M2cmdよりDB接続する際に必要となるDB接続情報を定義しておく必要があります。
@echo off
rem 【説明】新・現行からSELECT文でデータを取得し、CSVファイルに出力する。
rem 【前提①】[NEW_SQL]フォルダに新システムから比較検証データを取得するSQL(テーブル名.sql)を作成しておくこと。
rem 【前提②】[OLD_SQL]フォルダに現行システムから比較検証データを取得するSQL(テーブル名.sql)を作成しておくこと。
rem DB接続文字列取得(NEW_CONNECTION/OLD_CONNECTION)
call connection_string.bat
「@echo on
」以降の処理がログファイルへ出力されます。
①実行対象batから指定された引数(テーブル物理名)より、実行対象のSQLファイルを設定します。
@echo on
rem ---------------------------------------------------------------------------
rem 検証対象のテーブル名取得
set TARGET_TABLE=%1
rem SQL文格納先パス設定
set NEW_SQL_PATH=NEW_SQL\%TARGET_TABLE%.sql
set OLD_SQL_PATH=OLD_SQL\%TARGET_TABLE%.sql
A5M2cmdを使用し、DBからデータを取得 & CSVファイルへ出力しています。
/FileName
で実行対象のSQLファイルを指定、/FilePattern
で取得結果の出力先を指定しています。(もう一方のデータ取得も同様。)
rem 新システムのデータ取得
A5M2cmd "/Connect=%NEW_CONNECTION%" ^
/RunSQL ^
/FileName=%NEW_SQL_PATH% ^
/FilePattern=%NEW_CSV_FOLDER%\%TARGET_TABLE%.csv
③データ比較bat(99_compare_new_and_old_folders.bat)の解説
②データ取得batで出力したCSVファイルが格納されているフォルダを比較します。
@echo off
rem 【説明】WinMergeコマンドによりフォルダごと比較する。
rem 比較結果は[yyyymmdd/ジョブ名_RESULT/ジョブ名_フォルダ比較.html]に出力する。
こちらも「@echo on
」以降の処理がログファイルへ出力されます。
WinMergeコマンドオプションの意味合いについては、コード内に説明を追記しました。
@echo on
rem ---------------------------------------------------------------------------
rem WinMergeコマンドで新旧フォルダ比較
WinMergeU %NEW_CSV_FOLDER% %OLD_CSV_FOLDER% ^
/minimize ^ ⇒最小化状態でWinMergeを開始
/noninteractive ^ ⇒比較終了後にWinMergeを閉じる
/wl ^ ⇒読み取り専用で開く(左)
/wr ^ ⇒読み取り専用で開く(右)
/u ^ ⇒パスを最近使用した項目に追加しない
/ignorews ^ ⇒空白を無視する
/enableexitcode ^ ⇒比較結果を終了コードに設定(0: 同一, 1: 差異あり, 2: エラー)
/cfg Settings/IgnoreSpace=2 ^ ⇒空白「すべて無視」に設定
/cfg Settings/DirViewExpandSubdirs=1 ^ ⇒自動的にサブフォルダーを展開する
/cfg ReportFiles/ReportType=2 ^ ⇒「シンプルなHTML形式」でレポート出力
/cfg ReportFiles/IncludeFileCmpReport=1 ^ ⇒ファイル比較レポートを含める
/or "%RESULT_FOLDER%\%JOB_NAME%_フォルダ比較.html" ⇒レポート出力先
rem フォルダ比較結果を確認(0: 同一, 1: 差異あり, 2: エラー)
echo 比較結果:%ERRORLEVEL%
👇参考にさせていただいたサイト
ちなみに「/cfg Settings/etc...
」や「/cfg ReportFiles/etc...
」などの値は、WinMergeの設定ファイルを出力して、実際の設定値を見ながら指定してみてもいいと思います。
あとがき
この自動比較検証スクリプトを作成したおかげで、「新システムと旧システムの実行が終わったタイミングに、JP1から検証スクリプトをキックするように設定しておくだけで、あとは放置でOK」な状況を作り出すことができました。単純作業はどんどん自動化して幸せになりたいですね。
ただ、こちらのスクリプトは私が社会人3年目の時に作ったものなので、改善の余地はたくさんあると思います。ご助言などあればコメントをお願いいたします。
ここまで読んで下さりありがとうございました。