SQLServerに作ったテーブルのDDLをコマンドでサクッとエクスポートしたかった話

SQLServerで新しいテーブルを作成する際、楽なのでSQLServer Management Studio(以下SSMS)でGUI操作でテーブル、インデックス作成をしています。それはそうとしてDDL(CREATE TABLE文)は必要になるわけですね。チームメンバーに展開したり、新規にテスト環境を立ち上げることもありますので。
急を要する場面もなかったためDDLもSSMSのGUI操作でエクスポートしていました。当然ですが毎回同じ条件をポチポチクリックして指定していたわけです。それなりに手間がかかっていました。
さすがに「プログラマーのくせに毎回GUIで手作業wwwww」と思い始め、「こんなもん普通に考えてコマンドでできるじゃろ!!」というわけで、雑でいいのでbatファイルにでもできれば、と取り掛かってみました。

できませんでした

どうやらSQLServer本体、SSMSだけではできないようでした。データのエクスポート・インポートならばbcpコマンドもあるので、DDLエクスポートの口くらいあるだろうと思っていましたが裏切られました。

mssql-scripter

DDLの生成&出力をコマンドで行うにはmssql-scripterというツールが必要でした。(いや、PowerShellとかで頑張ればできると思いますが)
プログラマーというのは怠惰な生き物です。楽しましょう。
mssql-scripterはインストールが必要です。更にインストールはpipで行いますのでPythonのインストールも必要になります。

画像1

私はたまたま以前DockerDesktopで遊んでいた時にPythonがインストールされていましたので、今回はpipのアップグレードからやりました。

pip install -U pip

完了したら続いて

pip install mssql-scripter

完了時のキャプチャ等も残っていないのでお見せできませんが、特に躓くところもないかと思います。困ったらググってください。
私も困ったのでググりました。何に困ったか。
「特定スキーマのみ指定」はできるようなのです。

--include-objects dbo.

……ですが、同一スキーマ内でワイルドカードを使いたいのです。
こんなイメージで。

--include-objects t_my_*

指定方法を探した結果
正規表現でフィルタリングしたい

The answer is no.

あぁ無情。なんだか冷たく突き放された感。
ということで少なくとも今のところ実装しないという結論に至っていますので、諦めて対象テーブルを列挙することにします。

sub.bat

@echo off
set SERVER_NAME=%1
set DATABASE_NAME=%2
set USER_NAME=%3
set PASSWORD=%4
set DIRECTORY=%5
set PREFIX=%6
set TABLE_NAME=%7

if "%SERVER_NAME%" == "" (goto error)
if "%DATABASE_NAME%" == "" (goto error)
if "%USER_NAME%" == "" (goto error)
if "%PASSWORD%" == "" (goto error)
if "%DIRECTORY%" == "" (goto error)
if "%PREFIX%" == "" (goto error)
if "%TABLE_NAME%" == "" (goto error)

mssql-scripter -S %SERVER_NAME% -d %DATABASE_NAME% -U %USER_NAME% -P %PASSWORD% --exclude-use-database --include-objects %TABLE_NAME% --exclude-headers -f %DIRECTORY%\%PREFIX%.%TABLE_NAME%.sql
exit

:error
echo パラメータを全て設定してください。
pause > nul
exit

main.bat

@echo off
set SERVER_NAME=localhost
set DATABASE_NAME=
set USER_NAME=
set PASSWORD=
set DIRECTORY=..\DDL

if "%SERVER_NAME%" == "" (goto error)
if "%DATABASE_NAME%" == "" (goto error)
if "%USER_NAME%" == "" (goto error)
if "%PASSWORD%" == "" (goto error)
if "%DIRECTORY%" == "" (goto error)

START /min cmd /c .\sub.bat %SERVER_NAME% %DATABASE_NAME% %USER_NAME% %PASSWORD% %DIRECTORY% table t_my_table_a
START /min cmd /c .\sub.bat %SERVER_NAME% %DATABASE_NAME% %USER_NAME% %PASSWORD% %DIRECTORY% table t_my_table_b
START /min cmd /c .\sub.bat %SERVER_NAME% %DATABASE_NAME% %USER_NAME% %PASSWORD% %DIRECTORY% table t_my_table_c

echo 他のコマンドプロンプトが全て閉じられるまでお待ちください。
pause > nul
exit

:error
echo パラメータを全て設定してください。
pause > nul
exit

sub.bat → mssql-scripter のコマンドをラップしたbat。
main.bat → sub.bat を呼ぶbat。こちらに対象テーブルを列挙します。
(bat久しぶりすぎて予約語を大文字にするか小文字にするか悩んでいる)
main.batを叩くと対象テーブル分sub.batのプロンプトが最小化状態で立ち上がるようになっています。main.batのプロンプト以外が全て自動で閉じられたら処理完了です。
完了は目視確認っていう中途半端な対応ですが、特に困っていないので現状はコレで。時間があったら全て完了するまで待って終わったら閉じる系に直してもいいと思います。できるか知らんけど。

まとめ

・SQLServer本体とSSMSだけではbat化できなかった。
・mssql-scripterというツールで実現。
・Pythonからインストールしなきゃいけないのが若干不本意。
・面倒なことは自動化、半自動化するに限りますね。
・goto とか5億年ぶりに書いた気がする。

この記事が気に入ったらサポートをしてみませんか?