読者です 読者をやめる 読者になる 読者になる

命名って難しい

変数、関数、クラスなどなど実装より命名に毎回悩むタイプの人間による技術や趣味についてのメモ。

SQL ServerのDBの全テーブルをエクスポート/インポートしちゃうバッチ。

開発機でDBを空にしたり戻したりめっちゃ面倒なので作ってみました。

バッチ

エクスポートするバッチ

ExportAllTables.bat

ソースコード

@echo off
setlocal
pushd %~dp0

:--------------------------------------------------------------------------------
: 概要:対象データベースの全テーブルをエクスポートする。
: 引数:
:   %1-対象のサーバー
:   %2-対象のデータベース名
: 特記事項:サーバーへのアクセスは信頼関係接続で行う。
:--------------------------------------------------------------------------------

:--------------------------------------------------------------------------------
: 変数
:--------------------------------------------------------------------------------
: Powershellで日付の文字列[yyyyMMdd_HHmmss]取得
powershell -Command "echo (Get-Date).ToString('yyyyMMdd_HHmmss')" > %temp%\dayvalue
set /p ymd=<  %temp%\dayvalue

: DB設定
set Server=%~1
set DB=%~2

: 引数チェック
if "%Server%"=="" ( exit /b 1 )
if "%DB%"=="" ( exit /b 2)

: サーバー名の指定 [\\SERVER\INSTANCE] 形式でフォルダ名にできないので [SERVER.INSTANCE]形式に変更する
powershell -Command "'%Server%'.Replace('\\','').Replace('\','.')" > %temp%\serv
set /p ServerFolderName=< %temp%\serv

: 保存先フォルダ(サーバー名とデータベース名で基底のフォルダを作る)
set BaseDir=%ServerFolderName%-%DB%\
set SaveDir=%BaseDir%%ymd%\

: 対象DBのテーブル一覧
set TableList=TableList.txt
:--------------------------------------------------------------------------------
: メイン処理
:--------------------------------------------------------------------------------
mkdir %BaseDir%
mkdir %SaveDir%

: 対象DBのテーブルのリストを取得
bcp "select name from %DB%.sys.tables" queryout %TableList% -S%Server% -T -c -t; > nul

: 出力したテーブルのリストから1行ずつバックアップする。
for /f "delims=" %%i in (%TableList%) do (
  call :ExportTable "%Server%" %DB% %%i "%SaveDir%"
)

: テーブルリストを出力先に移動する。
: ※サーバーを(local)で指定された場合に、テーブルリストのパスがforコマンドで読めないパスになるため
move %TableList% "%SaveDir%%TableListDst%"

popd
endlocal
exit /b

:--------------------------------------------------------------------------------
: テーブルをバックアップする。
:--------------------------------------------------------------------------------
:ExportTable
setlocal

set server=%~1
set db=%2
set table=%3
set saveDir=%~4
set filePath=%saveDir%%table%.txt

bcp %db%.dbo.[%table%] out "%filePath%" -S%server% -T -c > nul

endlocal
exit /b

動作

対象のサーバーの対象のデータベースの各テーブルをBCPでエクスポートする。
実行日時のフォルダに格納されるのでその時点のデータベースをスナップショットできます。
BCPでエクスポートしているので、テキスト差分などでデータの相違を比較することも簡単になりました。

インポートするバッチ

ソースコード

CleanImport.bat

@echo off
setlocal

:--------------------------------------------------------------------------------
: 概要:ExportAllTables.batによりエクスポートされたフォルダから
:      対象のデータベースにクリーンインポートする
: 引数:
:   %1-対象のサーバー
:   %2-対象のデータベース名
: 特記事項:サーバーへのアクセスは信頼関係接続で行う。
:--------------------------------------------------------------------------------

:--------------------------------------------------------------------------------
: 変数
:--------------------------------------------------------------------------------

: DB設定
set Server=%~1
set DB=%~2
set tablesDir=%~3

: 引数チェック
if "%Server%"=="" ( echo exit /b 1 )
if "%DB%"=="" ( exit /b 2 )
if not exist %tablesDir% ( exit /b 3 )

: 対象DBのテーブル一覧
set TableList=TableList.txt

:--------------------------------------------------------------------------------
: メイン処理
:--------------------------------------------------------------------------------
set baseDir=%~dp0
pushd %tablesDir%
if not exist %TableList% ( exit /b 4 )

: 出力したテーブルのリストから1行ずつクリーンインポートする。
pushd %tablesDir%
for /f "delims=" %%i in (%TableList%) do (
  call :CleanImportTable "%Server%" %DB% %%i
)
popd

endlocal
exit /b 0

:CleanImportTable
setlocal

set server=%~1
set db=%~2
set table=%3

sqlcmd -S (local) -Q "truncate table %db%.dbo.[%table%]"
bcp %db%.dbo.%table% in %table%.txt -T -S%server% -c

endlocal
exit /b

pause

動作

指定のサーバーとデータベースに対して指定のフォルダの中のエクスポート済データをインポートする。
前述のエクスポートしたデータベースの状態にします。
TruncateしてBCPでインポートするだけ。割とテストとバグ再現などで活躍してます。

感想

BCP最高~