バッチスクリプトでテストデータ複製


背景・経緯

会社で提供しているWebシステム(地図上に顧客データをマッピングする、営業活動支援ツール)で性能課題がしぶとく残っていて、今期で何とか解消しようということで案件化したものの、テスト環境に性能検証用のデータ(大量データ)をつっこむようなツールもない。
やろうと思えば本番データをマスキングして取り込めば本番想定件数の確認はできるが、たとえば「表示対象の顧客データが10000件ある場合だと何秒くらいかかる?」みたいな検証パターンに対応できない(厳密にはできなくはないんだけど手作業での対応にめちゃくちゃ時間がかかる)

実施したこと

そういえばスクリプトもロクに書けないなぁというコトで、勉強を兼ねて、アナクロだけどテストデータを1件用意すれば、何件データを作るかさえちょこっと書き換えて実行すればその分だけテストデータを複製してくれるバッチスクリプトを作った。

@echo off

rem テストデータ作成処理

rem 遅延環境変数に対応
SETLOCAL enabledelayedexpansion

rem カレントディレクトリ指定
cd /d %~dp0

rem ループ制御用
set cnt=1
rem ループ回数
set loop=1500

set str0=abc

rem 入力ファイルを同じフォルダに置く
for /f "delims=" %%A in (in_table1.csv) do (
  rem レコードを変数にセット
  set str0=%%A

  call :outputfile
)

exit /b

rem サブルーチン(レコード編集・出力処理)
:outputfile

  rem 1-35バイトを抽出
  set str1=!str0:~0,35!
  rem 36-43バイト(顧客キー)を抽出
  set str2=!str0:~35,7!

  :next 

  rem 顧客コードに1を加算
  set /a str2 = str2 + 1
  set str3=!str0:~42,32!
  set str4=!str2!
  set str5=!str0:~81!
  rem 顧客コード編集後レコード
  set str6=!str1!!str2!!str3!!str4!!str5!

  rem 出力
  echo !str6! >> output_table1.sql

  set /a num = num + 1
  echo !num!
  echo !loop!

  if !num! gtr !loop! (
    exit /b
  ) else (
    goto :next
  )

ENDLOCAL

つまずきポイントなど

1.for文の中の変数が更新されない
 %で囲んだ変数はfor実行時の値でループ処理が実行される

 解決策:①遅延環境変数を使う
     ②ループ処理内部の変数は!で囲む
     →その行の処理が実行される時点で変数の値を再取得する

2.for文の中ではgotoを使ったループができない
 for文の中ではラベル(:)が記述できない

 解決策:for文の中でのループ(二重ループ)にしたい部分をサブルーチン化する。
     その上で、サブルーチン内にgotoを使ったループ処理を書く

3.半角スペースまでしかレコードが読み込まれない。

 解決策:for文の「delims」(デリミタ/区切り文字)に何も指定しないことで、
     各行の最後の文字まで読み込むようにする。

今後の課題

1.複製する件数や入力ファイル名は実行に入力パラメータとして渡せるようにする。

2.レコード長が変わっても対応できるように区切り位置も変数化する。

3.そもそも、各テーブル定義はきちんとデータ化されてるんだから、
  テーブルIDと欲しい件数を指定すればレコードを作成してくれるツールがそう手間をかけずに作れる、ハズ。

あんまり時間もない中で手早くできそうってコトでバッチスクリプトで何とかしたけど、今後はどこかで時間を確保して汎用的に使えるツールにしていきたい。

※課題は近々解消して記事も更新します。
 妥当性を気にするほどの規模でもないけど、これくらいのスクリプトは何も見ずにパパッと書けるようになりたい。