埋め込みクエリの書き方について
#2015/01/15 追記: Visual Basic 14 より VB にも逐語的リテラル文字列(Multiline string literals)が実装されました
埋め込みクエリの書き方については、昨年 Yahoo! のブログでも色々議論があり、大恥をかきつつも大変勉強させて頂きました。あれからだいぶ経ちましたが、今更ながら整理してみたいと思います。
以降、以下のクエリを叩き台にして考えてみます。(ちなみに MySQL のクエリである)
まず従来のありがちなパターン。
まずは、ありがちなクエリの書き方を挙げてみます。VB と C# のサンプルを用意しました。
VB は行末のアンダーバーがとってもうざいですね。でも VisualStudio 2010 なら、改行する際のアンダーバーとやっとおさらばできます。うれしいですね♪ (この機能、暗黙の行連結というそうだ・・・)
まぁ動かすことだけ考えるなら別にこれでいいのでしょうが、データベース側でクエリーログを取得した場合、以下のように一行だけのクエリになってしまい、非常に読みづらくなってしまいます。
ちょっと工夫を加えてみる
前項の書き方の欠点として、データベース側でログを見たとき、改行が全くないのでログが見にくくなります。そこでクエリに改行を入れてみましょう。クエリログが見やすくなるので、デバッグも非常にしやすくなります。
ログは見やすくなりますが、今度はコードが見にくくなってしまいました。C# はまだ許せるとしても、VB は可読性が劇的に下がった感がいたします。そこで、改行を先頭に移動してみましょう。
どうです?かなり読みやすくなったと思いませんか?
さらにもうひと工夫加えてみる。
データベース側でクエリを拾っても、どのクラスから投げられたクエリかよく判らないため、すぐにデバッグできないという問題があります。そこでクエリの先頭にコメントを入れてみましょう。
データベースの種類によって、実行プラン生成時にコメントが削られてしまう製品もあるようですが、MySQL ならログにしっかりコメントが出力されます。スロークエリログでどのクエリが時間がかかっているか調べる時などに、コメントをクエリに埋め込んでいれば、どのクラスのどのメソッドから投げられたクエリが時間がかかっているかすぐ調べられるため、たいへん便利です。
さて、ここまでは + 演算子を使ってクエリ文を結合してきたのですが、VB.NET なら & 演算子の方がいいという話がありましたね。以下 MSDN より引用します。
& 演算子 (Visual Basic) は、String オペランドに対してだけ定義されており、Option Strict の設定にかかわらず、常にオペランドを String に拡大変換します。文字列の連結には & 演算子を使用することをお勧めします。この演算子は文字列だけに定義されているので、意図しない変換が発生する可能性を減らすことができます。
http://msdn.microsoft.com/ja-jp/library/te2585xw.aspx
だそうです。で、& 演算子を使えば、以下のようになるわけです。ちなみに C# では & 演算子を使って文字列の結合はできません。
StringBuilder を使った書き方
クエリ文字列を作成するには、文字列を演算子で結合させるだけでなく、StringBuilder を使って生成する方法もあります。
AppendLine がうざいよ〜という意見もありますが、StringBuilder 使うメリットは一行一文として扱えるので、途中改行をいれたり、メソッドをクエリの途中に挿入できたりするので、個人的には気に入ってます。
後 vbCrLf ってVB6時代の遺物だと思っているので個人的にあまり好きではありません。こちらの方が、いかにも「俺どっとねっと使ってるぜぇ〜」的な書き方なので、自己満足に浸れるというオマケも付いてますしねw
結局ストアドが一番いいという意見も。
SQLServer なら、ストアドにしておけば、プログラム内のクエリを減らせる上に、データベース側で実行プランが生成され、プリコンパイルされた状態で保存されるため、同じクエリでもプログラム側から発行するより速度の向上が見込めます。ただし、残念ながら MySQL の場合はストアドがプリコンパイルして保存されないため、ストアドの性能は期待できないそうです。