FM牛鍵屋本舗

プログラマ(弱)の日々精進系ブログ

SQLServerをコマンドラインで使うよ!!

SQLServerコマンドラインで使うよ!!

※ 環境はWindowsです

単体テストしてて、DBダンプのエビデンスをA5M2で取得していたんですが、
SQL発行するの面倒くさい!!
貼り付けるの面倒くさい!!

コマンドラインでいい感じに出来ないかなーと調べてみたら
sqlcmdというCLIツールが用意されていました。

また、clipというコマンドでクリップボードコピーが。

おお、スクリプト作れるじゃない。

USE hoge;
SET NOCOUNT ON
GO

SELECT '○○テーブル';
SELECT '', 'カラム名1'...;
SELECT '', * FROM table_name;

GO
sqlcmd -S 127.0.0.1 -U user_name -P password -h -1 -W -s "<TAB>" -i sqlファイル | clip
-S 対象サーバー
-U ユーザー名
-P パスワード
-W 余計なホワイトスペースなし
-h -1するとヘッダが削除できる
-i 読み込むSQLファイル
-s セパレータ。TABはタブ文字をダブルクォートで囲む

オプションの詳細はhttps://docs.microsoft.com/ja-jp/previous-versions/sql/sql-server-2008-r2/ms162773(v=sql.105)あたりに書いてあります。

SQLServerに存在するオブジェクトのDDLが欲しいよ!!

諸元

と、掲題の通りの要望がありました。   業務処理ではなく、運用管理のためです。  もちろん、SQLServerManagementStdioのGUI操作で簡単に出来るのですが、しばしば行われるとそれすら面倒くさいという例のパターン。(https://technet.microsoft.com/ja-jp/library/ms178078(v=sql.105).aspx) そして、必要であればなるべくならデータも取得したいとのことで。

個人的にはこういうツールに頼るより、データベースマイグレーションツールで世代管理したいんだけどなー。

WindowsPowerShellを使う

https://qiita.com/nakaji/items/91aa1986ba68232e6129

こちらなどでも紹介されているとおり、Windows系のシェルツールっぽいやつで実現できるみたいです。

が、移植性低いし、他の方法ないかなーと。

mssql-scripterを使用する

これはまだ正式リリース前のpublic review版であると思うのですが、使えました。 pythonで作られているため、python環境が必須になります。 また、READMEの通り、pipにてインストールを行うようです。

仕事用の端末はWindowsだったので、実行形式インストーラーで3.6.xのpythonを入手。 そしてmssql-scripterをインストール。

pip install mssql-scripter

ヘルプは以下の通り。

mssql-scripter -h

様々なオプションがあるので、きめ細やかに制御出来ますが基本は以下の通り。

mssql-scripter -S <サーバ名> -U <ユーザ名> -P <パスワード> -f <出力先ディレクトリ> -d <対象データベース>

色々オプションを工夫してbatファイル作っておけば、急な出力要請も怖くない!!

jsessionidとsastrutsのタグライブラリの罠と戦ったよ!!

外部オープンにオープンする機能を書いていて、どこからリンクを設定するかが未定だったのでとりあえずURL直叩きで動作確認を行っていました。その中で、他機能の詳細画面(こちらも公開)へ飛ばす処理があったのですが、これがまた特定条件下の場合に404エラーに。

事象自体は割りとすぐにあたりがついて、「ブラウザのキャッシュクリア」後に「初回の詳細画面リクエスト」が失敗。理由はURLに;jsessionidがくっついていたから。 というよりも、パラメータとなる識別子をURLに含む、いわゆるRestっぽいURIで実現しようとしていたのですが、そのパラメータが;jsessionidでかき消されているというか。 ちなみに、hidden項目でURLをHTML上に保持して、クリックイベント着火で対象のSEQ取得、location.hrefで遷移、という形をとっていました。

色々調べてみると、TomcatのHttpServletResponseのencodeURLの実装はデフォルトで、「CookieでセッションIDをやり取りしていない場合はURLリライティングでjsessionidを付加する」みたいな形になっている様子。

いやでも明示的に呼んでないぞそのメソッド…と途方に暮れていたのですが、呼んでましたよSAStrutsのカスタムタグで…。

f:url()

この記述は下記のurlメソッドを呼び出しています。 ざっくりいうと、コンテキストパスなどを含めたURLを補完してくれるメソッドです。

S2Functions

動的解析がうまくいかなかったのでとりあえずの推測になりますが、

  1. URL直指定でアクションメソッドを呼び出す
  2. 当然、cookieのjsessionidは指定されていない
  3. JSPコンパイル時、;jsessionidを付加したURLをHTMLを出力 1. レスポンスヘッダーでcookieにjsessionid書き込み。
  4. ;jsessionid=XXXのURLにseqくっつけて遷移
  5. そんなURLないと怒られる

ということだったんだろうなあ。

対象文字を置換にすることで対応しました。

他の方法としては * PGRパターンっぽくリロードする * URLの出力方法を変更する * URLのパラメーターをやめてGET/POSTでのパラメータ渡しにする とかがあるのかな。

結城浩さんのプログラマの数学を読了したよ!!

プログラマの数学 第2版

備忘録的に。今後はもっとちゃんと書評書きたいな。

結城さんの本は昔、デザインパターン学習時に大変お世話になりまして、 以来、難しいことを分かりやすく丁寧に説明して頂ける文章のすっかりファンとなってます。

そして今回、僕のような理系苦手プログラマの鬼門である数学。 なんなら高校時代めっちゃ赤点でしたからね、数学。

1章 0の物語

  • なぜ0が必要なのか
    • ルールがシンプルになる
  • なぜコンピュータでは2進数が使われているのか。
    • コンピュータもわかりやすい方がいい
  • 指数法則
    • ...101 = 10, 100 = 1, 10^-1 = 1_/10...
    • 102 * 103 = 102+3

なんとなくプログラムの指数表現に対しても抵抗がなくなった気がする

2章 論理

  • 「もれ」や「だぶり」のない網羅的で排他的な分割を行う
  • 「ならば」という命題
  • カルノー図による論理の整理
  • 未定義を含む論理

プログラマとしては避けて通れない

if文がややこしくなったときに、テーブル駆動で対応してたんですが、 カルノー図で整理できたらもっと分かりやすく書けるかもしれないですね。

3章 剰余

  • 周期性と余りによる簡略化
    • 1010000日後は何曜日?

「問題を単純化する」ということは、 メソッドやクラス分割にもつながりますね。

4章 数学的帰納法

  • 「基底の証明」と「帰納の証明」で無限に対抗する
    • F(1)を証明する // 1でなくてもよい
    • F(n+1)が成り立つことを証明する

5章 順列・組み合わせ

すごいあやふやになんとなく解いていた5P3とか4C2がようやく腑に落ちました。 組み合わせの場合は「重複を取り除く」なんですね。 キーワードは「順列」「置換」「組み合わせ」。 前半は集合演算の基礎っぽいのもあったので、RDB理解に役立つかも。

6章 再帰

再帰的なメソッドはいままでにも書いたことがあるけど、 今ひとつループより可読性が落ちている気がしてました。 漸化式ならば再帰処理で実装したほうがよさそう。 漸化式は、前のn-1(1とは限らないけど)を利用して解にするような式。

7章 指数的な爆発

紙を折り続けると月に届くという話は有名ですが、そういえばドラ◯もんのバイバインも指数的な爆発起こしてますね。 指数的な爆発を含むときは総当りはNG。バイナリサーチ(二分探索)などのツールを使って対応する必要があります。 また、これまたあやふやだった、logを学べました。

8章 計算不可能な問題

背理法」というツールの紹介がありました。 証明したいことの否定を命題として仮定して、矛盾を探すという証明法です。

カウンタブルな集合とは、順序付けをすることが出来、漏れが存在しない集合。 カウンタブルかつ無限、はありえる、がカウンタブルでないかつ無限もまた存在する。

「停止判定問題の証明」というのも紹介されてましたが、これはなかなか僕には難しい…。 一度理解するまで読んでもしばらくするとあれれってなりますね。再読しよう。

9章 プログラマの数学とは

ここまでのおさらいと総括。 問題を「別の世界に移して考える」ことが大事なんだなーと。 問題を「抽象化・一般化する」のと合わせて、現実問題にも応用していきたいと思います。

付録1 機械学習への第一歩

「入力ベクトル」「出力ベクトル」「目標ベクトル」「重みパラメータ」などなど…。 あと「ニューロンネットワーク」や「深層学習」「予測問題」「分類問題」などなど…。 機械学習は要するに、与えられた「入力ベクトル」を基に「出力ベクトル」を「目標ベクトル」に近づくような形で コンピュータ自身が「重みパラメータ」を調整していくようなもの…なのかな。 今後重要なトピックなので、今後も学んでいきたいです。

過学習の説明の例がわかりやすかったです。

感想

ちょっと数学がす、好きになってき、きました。。。 プログラミングにあんまり理数系かって関係ないよなあ、 と思っていたけど 現実世界の法則のモデリングという意味では、 プログラムにもやっぱり近いのかな…。

RakeとGemとBundlerについて微妙な理解をするよ!!

たぶん、僕が仕事で書いてるJavaにとってはMavenとかGradle、ビルドツールとしてはAntなどに当たるんでしょうが、Javaを基準に理解をしようとしてもなかなか深まらない、これら。 とりあえず現時点での認識を備忘録的に記載しておきます。

そんな情報の不正確さについて長々と前置きを…。

Gem(RubyGem)

標準のパッケージ管理ツールgem install xxxで依存するgemパッケージを含めてインストール出来る。 ご飯屋さんで言えば、単品メニューか、それに味噌汁がついてくる感じだ。 gem helpgem help [command]で使い方が出る。 JavaでいえばMavenのpomって感じだ。

Rake

ビルドツールだ。Javaで言えばAntだ。 ご飯屋さんで言えば、財布にお金を入れたり、お店に向かったりすることだ。多分。

Bundler

自身もgemパッケージでgem install bundlerでインストールが可能な、アプリケーション単位でのパッケージ管理ツール。 言うなればコース料理か…。 bundle initを行うことで作成出来るGemFileを用いて、アプリケーション内(のさらに各工程ごと)に必要なGemの管理ができる。 また、bundle gemコマンドを利用することで、gemパッケージの雛形も作れてしまう。 なお、GemFile自体は他のフレームワークでも生成されることがあるそう。

Javaでbooleanの排他的論理和の否定を書くよ!!

今日既存ソースを眺めてて、大したことではないのだけれど、ある箇所が目に留まりました。 簡単に言えば2つのオブジェクトが両方ともnullかまたは両方ともnullじゃない場合にエラーにする処理で、コードにすると以下のように表せます。

Object a = createSomeObject();
Object b = createSomeObject();

if ((a == null && b == null) || (a != null && b != null)) {
  // エラー処理
}

うーん、冗長(な気がする)!!

ここで、a == nullを命題A、b == nullを命題B、理想とする結果をXとしてまとめます。

A B X
TRUE TRUE TRUE
TRUE FALSE FLASE
FALSE TRUE FLASE
FALSE FALSE TRUE

すなわち「等しい」という「排他的論理和」の否定になるため、以下のように書き換えることができます。

Object a = createSomeObject();
Object b = createSomeObject();

if ((a == null) == (b == null)) {
  // エラー処理
}

...なんかわかりずらくなりました。 可読性とどっちを取るかって話ですね。

Rakeではファイルすべてがまず評価されるよ!!

またまたパーフェクトRubyから。

Rakeのファイルタスクの説明でわからない部分があり、 ここ3日くらい頭を抱えたり鼻歌を歌ったりしていたんですが、 ようやく理解出来たので、記録として残しておきます。 願わくば同じ悩みを抱えている人を救えますように。いないか。

Rakefile上でファイルタスクを使うと、ファイルが存在しない場合の処理が記載できます。

file ファイル名 do |file_name|
  # ファイルを作るなりなんなり好きにすればいいさ!
end

もし、ファイル名に指定したものが存在している場合は実行されません。

さて、そんなファイルタスクの説明は、その前項での「ファイルが存在していない場合はエラーとして処理終了」なサンプルを改良するという形式をとっていました。

自分なりに消化して書くと、以下のような感じに。

TEXT_FILES = [
  'file1.txt',
  'file2.txt',
  'file3.txt
]

task :check => TEXT_FILES do
end

TEXT_FILES.each do |file_name|
  file file_name do
    sh "touch #{file_name}"
  end
end

僕は

TEXT_FILESなんてタスクないじゃん!! なんで動くのこれ!?

なんて思ってました恥ずかしい。

どうもいろんなところにputs仕込んで確認すると、 個別のタスクが実行される前に、 Rakefile全体がまず評価されることがわかりました。

そのため、

  1. :checkが評価される
  2. 依存しているTEXT_FILESはどこ…??
  3. TEXT_FILES.eachが何故か評価される

ではなく

  1. ファイルの全量が読まれTEXT_FILES.eachにより、配列要素すべてのfileタスクが定義される
    ※この際、タスク名はファイル名となる
  2. :checkが実行される
  3. 依存しているタスク名の配列(=ファイル名)の配列が順番に実行される

ということになるようです。 当たり前だけど、逐次実行ではないんだなあ。