憂国なプログラマ

背景を地味なパターンに直してみました。これはこれでいいかも!

全体表示

[ リスト ]

非常に多くの現場で、以下のような埋め込みクエリを見かけます。
Dim strSQL As String = _
    "SELECT c.id, c.code, c.name, c.zipcode, c.address, c.telphone FROM customer " & _
    "c WHERE c.id = " & id.ToString & " AND c.name LIKE '%" & name & "%' ・・・・"
これだとクエリが大きくなるほど可読性が低下する上、サーバーでログを見るとき

SELECT c.id, c.code, c.name, c.zipcode, c.address, c.telphone FROM customer ・・・・・

とすべて一行に繋がってしまい、クエリに問題があっても、どこに問題があるのかチェックしずらくなります。

しかし System.Text.StringBuilder をうまく使えば、クエリの可読性が劇的に向上し、サーバーに流れたクエリを拾う際も非常に見やすくなります。
Dim query As New System.Text.StringBuilder()
With query
    .AppendLine("SELECT ")
    .AppendLine("   c.id, ")
    .AppendLine("   c.code, ")
    .AppendLine("   c.name, ")
    .AppendLine("   c.zipcode, ")
    .AppendLine("   c.address, ")
    .AppendLine("   c.telphone ")
    .AppendLine("FROM ")
    .AppendLine("   customer ")
    .AppendLine("WHERE c.id = " & id.ToString & " ")
    .AppendLine("AND   c.name LIKE '%" & Name & "%' ")
    ・・・・
End With

さらにクエリの一行目にメソッド名をコメントとして設定すると、どのクラスのどのメソッドから投げられたのか、すぐ判るようになります。
Dim query As New System.Text.StringBuilder()
With query
    .AppendLine("-- CompanyName.TechnologyName.FeatureName.ClassName.MethodName")
    .AppendLine("SELECT ")
    .AppendLine("   c.id, ")
    .AppendLine("   c.code, ")
    .AppendLine("   c.name, ")
    .AppendLine("   c.zipcode, ")
    .AppendLine("   c.address, ")
    .AppendLine("   c.telphone ")
    .AppendLine("FROM ")
    .AppendLine("   customer ")
    .AppendLine("WHERE c.id = " & id.ToString & " ")
    .AppendLine("AND   c.name LIKE '%" & name & "%' ")
    ・・・・
End With
これならサーバーに流れるクエリは以下のようになり、大変保守しやすくなります。

-- CompanyName.TechnologyName.FeatureName.ClassName.MethodName
SELECT
  c.id,
  c.code,
  c.name,
  c.zipcode,
  c.address,
  c.telphone
FROM
  customer
WHERE c.id = 24
AND  c.name LIKE '%hogehoge%'


ただし上記のクエリは、セキュリティ上まだ不安が残ってます。以下のように SqlParameter クラスを使うと、SQLインジェクション対策ができます。
Dim query As New System.Text.StringBuilder()
With query
    .AppendLine("-- CompanyName.TechnologyName.FeatureName.ClassName.MethodName")
    .AppendLine("SELECT ")
    .AppendLine("   c.id, ")
    .AppendLine("   c.code, ")
    .AppendLine("   c.name, ")
    .AppendLine("   c.zipcode, ")
    .AppendLine("   c.address, ")
    .AppendLine("   c.telphone ")
    .AppendLine("FROM ")
    .AppendLine("   customer ")
    .AppendLine("WHERE c.id = @id ")
    .AppendLine("AND   c.name LIKE CONCAT( '%', @name, '%' ))
    ・・・・
End With

Dim command As New SqlCommand(query.ToString())
With command.Parameters
    .Add(New SqlParameter("id", id))
    .Add(New SqlParameter("name", name))
End With

要点をまとめると
1.埋め込みクエリは、& 演算子で結合せず、System.Text.StringBuilder を使う
2.StringBuilder.Append() ではなく StringBuilder.AppenLine() メソッドで改行を付けて結合する
3.一行目には、名前空間〜クラス〜メソッド名をコメントに加える
4.セキュリティ強化のため、SqlParameter を使ってクエリパラメータに値を渡すようにする
いかがでしょうか?
 

閉じる コメント(16)

顔アイコン

本当に StringBuilder は必要でしょうか?

Dim query As String = "SELECT " & vbCrLf _
& " c.id, " & vbCrLf ...

このようなコードでは不十分でしょうか?
この部分が性能のボトルネックになることは少ないでしょうが、
1千万回繰り返したところ、

StringBuilder : 6 秒以上
& による連結 : 0.1 秒以下

と、かなりの差が出ました。
一行になってしまうのだけが問題なら、こちらの方が素直でかつ高速な実装だと思います。

2009/8/13(木) 午後 1:20 [ bleis-tift ]

顔アイコン

こちらに反論を用意しております。(^ω^)
http://blogs.yahoo.co.jp/hilapon/4701167.html

> Dim query As String = "SELECT " & vbCrLf _
& " c.id, " & vbCrLf ...

実際に実装してみると判りますが、わたし的には

StringBuilder.AppndLine()

の方がよっぽど可読性が高く実装しやすいですよ。(^ω^)v

2009/8/13(木) 午後 2:37 [ hilapon ]

顔アイコン

> の方がよっぽど可読性が高く実装しやすいですよ。(^ω^)v

追記:
普通に ManagimentStudio や NaviCat でクエリ書いて、
構文や性能をチェックした後に
「.AppnedLine("」と「")」でサンドしてやるだけです。

この方がよっぽど作業が速いし、サーバーチームからも
綺麗に改行&インデントが入っているので喜ばれます。(^ω^)v

2009/8/13(木) 午後 2:43 [ hilapon ]

顔アイコン

えと、それのどこが反論になるのでしょうか^^;
もしや、文字列連結では SQL インジェクション対策にならない・・・と?
もう一度、よく考えてみてください。
SQL インジェクションに対策している部分は、StringBuilder を使用している部分ではなく、SqlParameter を使用している部分です。
これは、文字列結合であるかどうかは全く関係ありません。

また、おそらく可読性ではなく「書きやすさ」のことを言っているのだと思うのですが、
可読性と書きやすさは全く別のものです。
StringBuilder を用いたものと文字列連結を用いたもの、
どちらも可読性に差が出るとは思えません。

2009/8/13(木) 午後 2:51 [ bleis-tift ]

顔アイコン

> どちらも可読性に差が出るとは思えません。

まったくもって理解不能です。まさか

> Dim query As String = "SELECT " & vbCrLf _
& " c.id, " & vbCrLf ...

こんな & 演算子で繋げまくったクエリが
ほんとに可読性がいいとでも言われるのでしょうか?(^ω^;

あとサーバーログの読みやすさを考慮してますか?
複雑なクエリがインデントもなく一行で流れた場合
どれほどクエリが読みにくいか、
全く考慮にいれてないと思われます。(^ω^;

2009/8/13(木) 午後 3:01 [ hilapon ]

顔アイコン

どっちもどっちです>可読性
SQLを書くときは、SQLだけを見たいので、Appendしても
& _としても、あんまり変わりません。特に複数JOIN
してるようなSQLだと特にです。

サーバログは確かに改行あったらいいとは思いますが。

2009/8/13(木) 午後 3:38 [ mr_*_00*3 ]

顔アイコン

コメント欄が 500 文字に制限されている上、
スペースも消されてしまうため、伝わらなかったのかもしれません。
崩れるかもしれませんが、日本語入力 On の空白を使ってみますね。

Dim query As String = "SELECT " & vbCrLf _
& " c.id, " & vbCrLf _
& " c.code, " & vbCrLf ...

また、書きやすさの点で StringBuilder が優れているという点には異論はありません。
しかし、可読性の点ではどちらにも対して差はないと思います。

また、ログの読みやすさですが、一行で流さないために vbCrLf を使っています。

2009/8/13(木) 午後 3:39 [ bleis-tift ]

顔アイコン

ちなみに StringBuilder の場合、もう少し技が使えます。
インデントを維持したまま効果的にコメントを効果的に埋め込めます。
複合クエリの実例をお見せしましょう。

http://blogs.yahoo.co.jp/hilapon/5376925.html

2009/8/13(木) 午後 4:37 [ hilapon ]

顔アイコン

> もしや、文字列連結では SQL インジェクション対策にならない・・・と?

文字列結合よりも SQLParameter を推奨する理由は、以下にあります。
http://msdn.microsoft.com/ja-jp/library/ms161953.aspx

2009/8/13(木) 午後 4:54 [ hilapon ]

顔アイコン

えと、ちょっと認識がずれている気がします

・vbCrLf の意味は分かっていますか?
・パラメータの SQL へのバインドに文字列結合を使用すると誤読していませんか?

2009/8/13(木) 午後 5:05 [ bleis-tift ]

顔アイコン

> ・vbCrLf の意味は分かっていますか?

言わずもがな。でもわたし嫌いなんですw

> ・パラメータの SQL へのバインドに文字列結合を使用すると誤読していませんか?

読み方によってはそう取れますよ。

ブログの過去記事見ました。
「SQLParamater 使えよ」って言ってましたねw

2009/8/13(木) 午後 5:17 [ hilapon ]

顔アイコン

ちなみにVBも

"\n"

が使えたらよかったんですがね。(^ω^;

2009/8/13(木) 午後 5:33 [ hilapon ]

顔アイコン

通りすがりですが、、、

StringBuilder + SqlParameter に賛成です

Visualstudio上ではデバッグ時にコメントアウト
等の一次的な処理が容易になりますしね。

↓エラーにならない
With hoge
.AppendLine(" hoge1")
'.AppendLine(" hoge2")
.AppendLine(" hoge3")
End With
↓エラーになる
hoge = "hoge1" & vbcrlf _
' & " hoge2" & vbcrlf _
& " hoge3" & vbcrlf

ま、、好き嫌いあるとおもいますが・・・

2009/8/17(月) 午後 2:29 [ but-masaru ]

顔アイコン

私の例

●昔
sql = ""
sql &= " hoge1" & vbCrLf
sql &= " hoge2" & vbCrLf
sql &= " hoge3" & vbCrLf

●今
sql = ""
sql &= $" hoge1 {vbCrLf}"
sql &= $" hoge2 {vbCrLf}"
sql &= $" hoge3 {vbCrLf}"

今はこうも書けるらしい
sql = "
__hoge1
__hoge2
__hoge3
"
ただしこれだと上の「通りすがりですが、、、」さんが
書いている問題が解決できないので嫌いです。
(最後の例の __ はスペースに読み替えてください。投稿行がTrimされるようなので。)

2015/8/26(水) 午後 8:08 [ 通りすがりです ]

顔アイコン

StringBuilder は 「.AppendLine()」 が目障りだし、
文字列連結では 「& vbCrLf _」が目障りだと感じるので
私の場合 string.Join() を好んで使います。

Dim query = string.Join(vbCrLf, {
"SELECT ",
" c.id, ",
" c.code, ",
" c.name, ",
" c.zipcode, ",
" c.address, ",
" c.telphone , ",
" ..."
})

パフォーマンスは StringBuilder と同等になります。

2017/10/25(水) 午前 9:55 [ s.s ]

顔アイコン

StringBuilderがいいね
+で連結は見辛くて一番迷惑

2018/2/10(土) 午前 9:17 [ thr*e*reeri*er ]


.
hilapon
hilapon
男性 / AB型
人気度
Yahoo!ブログヘルプ - ブログ人気度について
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

過去の記事一覧

よしもとブログランキング

もっと見る

[PR]お得情報

話題の新商品が今だけもらえる!
ジュレームアミノ シュープリーム
プレゼントキャンペーン
ふるさと納税サイト『さとふる』
実質2000円で特産品がお手元に
11/30までキャンペーン実施中!

その他のキャンペーン


プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

みんなの更新記事