none
VB,InputBox関数で代入した値(文字型)を含む表現での検索法を教えてください。 RRS feed

  • 質問

  • InPutBoxを表示し、そこに値を入れます(例:AA)。 その値(AA)を含む表現で、別の個所で検索したいのですが、うまくいきません。

    ShortName---会社名です。 会社名の中に「AA」を含む会社を検索したいのです。 データは、サーバーから引き出しDtaTableにあります。 最後に、コードの一部を記します(4~6)。

    (1) ShortName Like '%()%' --左記の% と%の間()に、実際の表現(AA)を入れた時は、うまくいきます。

    (2) ShortName Like '%" & SHN & "%' ---左記の状態で、 Public SHN As String=”AA” とした場合も、うまくいきます。

    上記1と2は、実際には使用できません。

    下記の、4~6のようなやり方で実験したのですが、駄目でした。 うまくいけば、大きく前進するのですが。

     Like '%" & SHN & "%' の中の、" & SHN & "が駄目なようです。 ’" & SHN & "’と「'」を両端に入れると、もっと悪くなりエラー表示になります。

    以下4~6は、私のコードです。 間違いの指摘、ならびにもっと良い方法があれば、それを教えていただければ幸いです。

    Yksaila

    作成コード(4~6):

    (4)  Public SHN As String

    (5)  Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
             Dim MyChar
             MyChar = InputBox("名前を入力してください。")
             SHN = MyChar
             MsgBox(MyChar & "を入力しました。")---これは、実際は不要(参考に表示するだけ)
        End sub

    (6) 'コンボボックス:T_M_Client ----コンボボックス(CB_ParentClient_ID)表示準備 '子会社(支店): FLG_Branch= -1は、除く。
            Dim dsCombo3 = New DataSet
            Dim sqCombo3 As String
            sqCombo3 = "SELECT T_M_Client.Client_ID, T_M_Client.ClientCode, T_M_Client.ShortName FROM T_M_Client " &
                       "Where FLG_Branch= 0 and ShortName Like '%" & SHN & "%' order by Kanacode"
            adapter.SelectCommand = New SqlClient.SqlCommand(sqCombo3, Con)
            adapter.SelectCommand.CommandType = CommandType.Text
            adapter.Fill(dsCombo3)
            Dim dtCombo3 As New DataTable
            dtCombo3 = dsCombo3.Tables(0)
            'Me.DataGridView1.DataSource = dtCombo1---使用せず
            Me.CB_ParentClient_ID.DataSource = dtCombo3
            Me.CB_ParentClient_ID.DisplayMember = "ShortName"
            Me.CB_ParentClient_ID.ValueMember = "Client_ID"

    2012年4月29日 10:45

回答

  •  VB とありますが、VB のバージョンは何でしょうか。最新のバージョンであるなら、文字連結を使用せず、String.Format メソッドを使用してください。

    sqCombo3 = String.Format("SELECT T_M_Client.Client_ID, T_M_Client.ClientCode, T_M_Client.ShortName FROM T_M_Client Where FLG_Branch= 0 and ShortName Like '%{0}%' order by Kanacode", SHN)
    

     もう一ついうなら、文字連結せず、パラメータ クエリを使いましょう。


    Jitta@わんくま同盟

    • 回答としてマーク yksaila 2012年4月30日 0:20
    2012年4月29日 13:20

すべての返信

  •  VB とありますが、VB のバージョンは何でしょうか。最新のバージョンであるなら、文字連結を使用せず、String.Format メソッドを使用してください。

    sqCombo3 = String.Format("SELECT T_M_Client.Client_ID, T_M_Client.ClientCode, T_M_Client.ShortName FROM T_M_Client Where FLG_Branch= 0 and ShortName Like '%{0}%' order by Kanacode", SHN)
    

     もう一ついうなら、文字連結せず、パラメータ クエリを使いましょう。


    Jitta@わんくま同盟

    • 回答としてマーク yksaila 2012年4月30日 0:20
    2012年4月29日 13:20
  •  VB とありますが、VB のバージョンは何でしょうか。最新のバージョンであるなら、文字連結を使用せず、String.Format メソッドを使用してください。

    sqCombo3 = String.Format("SELECT T_M_Client.Client_ID, T_M_Client.ClientCode, T_M_Client.ShortName FROM T_M_Client Where FLG_Branch= 0 and ShortName Like '%{0}%' order by Kanacode", SHN)
    

     もう一ついうなら、文字連結せず、パラメータ クエリを使いましょう。


    Jitta@わんくま同盟

    上記のとおりやりました(貼り付けでやりましたので書き間違いは、ないはずです)が、正常に動きません。 なぜでしょうか? 

    VBのバージョンは、VB 2010 Express です。  (-----Like '%{0}%'---",SHN) あたりに問題があるのでしょうか? 

    それと、すいませんが、ここでのパラメータクエリは、どう書けばよいのでしょうか?

    YKsaila

    2012年4月29日 15:32
  • 上記のとおりやりました(貼り付けでやりましたので書き間違いは、ないはずです)が、正常に動きません。 なぜでしょうか? 

    なぜかを突き止めるのはあなたの仕事です。
    間違いはないはず、正常に動かないというだけで何かわかる人はいません。

    とりあえず、ブレークポイントを貼って、sqCombo3 とやらがどんな値になったかを確認してください。
    MsgBox なんて使わなくても、デバッグすればいいんです。ブレークポイントが何かわからないのであれば、C# の記事ですがこのあたりとか参考になりますか。

    それと、すいませんが、ここでのパラメータクエリは、どう書けばよいのでしょうか?

    「パラメータクエリ VB.NET」などで探した結果で質問されていますか?
    プログラマーなのですから、自分で試した、調べた事柄を明らかにして、その上で疑問を投げかけることをしていきましょう。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。

    2012年4月29日 15:45
    モデレータ
  • azuleanさんへ

    ご忠告ありがとうございます。

    >なぜかを突き止めるのはあなたの仕事です。 間違いはないはず、正常に動かないというだけで何かわかる人はいません。

    たしかに、おっしゃる通りです、本当に。 一日中やっても(十数時間連続!)うまくいかず、つい ”溺れる者、藁をもつかむ”  の心境でいたのです、お許しください。 

    知識・経験不足のため、ついコードに不足があるのかと思い、書き込みしてしまいました。 コードには、なんの問題もありませんでした。 種〃、実験はしました!

    その結果、解決には至りました! 

    ブレークポイント・デバッグも使っていますが、上手でないのかもしれません。 現在使用中のソフトで、コードも結構多くて複雑なのです。

    >MsgBox なんて使わなくても、デバッグすればいいんです。

    まあ、そうなんですが、時間短縮で設定しただけでした。 いずれ消去するつもりでしたが、結局最終的には合ったほうがよくなり(当然、コメント内容は変更しました)、残しました。 使用する人の便宜上です。 (うるさいという苦情がでてくれば、外しますが)。

    解決にかんして:

    入れるべき他の個所に、肝心のコードを入れてなくて、うまくいかないことに気づきました。 そこに、同じコード群を追加したら、成功しました。

    お騒がせしました、ありがとうございます。 

    YKsaila

    2012年4月30日 0:20
  • JIttaさんへ

    ありがとうございます。 無事、解決しました。

    うまくいかなかった原因の一つは、コード群が多く複雑で、つい追加しておくべき個所に、当のコードを入れておかなかったせいでした。

    おかげさまで、次の段階へ進めます。

    Yksaila

    2012年4月30日 0:23
  • >(2) ShortName Like '%" & SHN & "%' ---左記の状態で、 Public SHN As String=”AA” とした場合も、うまくいきます。

    状況を見る限り、(6)のコードは正常に動いていそうです。(5)のButton1_Clickイベントハンドラ内でSHNをセットした後に検索を実行していませんが、他のタイミングで検索を実行しているのでしょうか?Azuleanさんも書かれていますが、自分の思い通りの検索結果が得られない場合、デバッグで自分の思い通りにコードが処理されていっているかを確認する必要があります。一発で正しいコードを書ける人は稀です。デバッグをしながら正しく動くコードを作り上げていきます。

    また、パラメータライズドクエリに関しては、以下のスレッドで既に経験済みだと思いますので、それを真似ればできると思います。わからなければまた質問して下さい。

    チェックボックスの値が、サーバーに移動反映しません。関連コードを表示します。
    http://social.msdn.microsoft.com/Forums/ja-JP/vbgeneralja/thread/94c2fe63-3f3b-4bea-81f1-14acac0dcd4d


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月30日 0:24
    モデレータ
  • trapemiyaさんへ

    ありがとうございます。

    そうなんです、私のコード自体には間違いはなかったようです。 でも、String.Formatが勉強出来たので、良かったです。

    >(5)のButton1_Clickイベントハンドラ内でSHNをセットした後に検索を実行していませんが

    おっしゃるとおりです。 ここに問題があったのです(この段階でのコード設定が抜けていました)。 デバッグしても気づかず、大変でした。

    気付くのに、丸二日もかかりました! 

    でも、皆さんのおかげで、連休中は平穏な気持で過ごせます。 連休中も少し進めますが、連休中に問題がでてこないことを祈っています。

    >また、パラメータライズドクエリに関しては、以下のスレッドで既に経験済みだと思いますので、それを真似ればできると思います。わからなければまた質問して下さい。

    再度挑戦してみます、前回は参考コードを手本にして書いたのでうまくいったのですが。 

    わからなくなりましたら、再度質問させてください、よろしくお願いします。

    YKsaila

    2012年4月30日 0:43
  • >MsgBox なんて使わなくても、デバッグすればいいんです。
    まあ、そうなんですが、時間短縮で設定しただけでした。

    デバッグ実行できるのであれば、ブレークポイント貼ってウォッチを見る方が、コードを触らずに済むので楽ですよ。
    コンパイル時間もかからないので、時間短縮になるかと思いますので、ぜひ今後も使ってみてください。

    ブレークポイントやウォッチ、ステップ実行を使えば、どのコードがどの順番で実行されて、どのような変数の状態になっているのかが見えるので、思っていた場所を通る・通らないもすぐわかります。

    入れるべき他の個所に、肝心のコードを入れてなくて、うまくいかないことに気づきました。 そこに、同じコード群を追加したら、成功しました。

    お聞きする限り、そのソースコードはかなり危険ですね。
    コピペコードが多いのか、似たようなコードが多いのでしょうけれど、そういったコードは今後も不具合を引き起こします。

    今のソースコードは仕方がないのかもしれませんが、将来的には同じコード・似たコードを書かない、クラスは小さくするといった設計技法やコーディング技法を上げるために、リファクタリングの書籍とか、CleanCode とか、いろいろと本を読んでみてください。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。

    2012年4月30日 0:45
    モデレータ
  •  trapemiyaさんへ

    パラメータライズドクエリについて、教えてください。

    前回は、見本を参考にいくつかパラメータライズドクエリを書き、うまくいっていました。 

    しかし、下記コードですと、「 変数 '@FLG_Branch' を宣言する必要があります。」とコメントがでてエラーになります。

    どこが悪いのでしょうか? sqcmbを下記のようですと、成功しています(エラー表示なし)。

     sqcmb = String.Format("SELECT T_M_Client.Client_ID, T_M_Client.ClientCode, T_M_Client.ShortName FROM T_M_Client " & _
            '                        "Where FLG_Branch= 0 and ShortName Like '%{0}%' order by Kanacode", SHN)

    エラーコード:

        con.open   ’サーバーとの接続を開いた後

            Dim adapter = New SqlClient.SqlDataAdapter()
            Dim dscmb = New DataSet
            Dim sqcmb As String
            sqcmb = String.Format("SELECT T_M_Client.Client_ID, T_M_Client.ClientCode, T_M_Client.ShortName FROM T_M_Client " & _
                                        "Where FLG_Branch= @FLG_Branch and ShortName Like @ShortName order by Kanacode", SHN)   ← おかしいところ
            SQL.Parameters.AddWithValue("@FLG_Branch", 0)
            SQL.Parameters.AddWithValue("@ShortName", "%{0}%")     ' '%{0}%'  ← ここもおかしいところ、'%{0}%' だとエラーになるので、 "%{0}%”としました。

            adapter.SelectCommand = New SqlClient.SqlCommand(sqcmb, Con)
            adapter.SelectCommand.CommandType = CommandType.Text
            adapter.Fill(dscmb)

    エラーコメント:変数 '@FLG_Branch' を宣言する必要があります。----これがOKになっても、次に、 SQL.Parameters.AddWithValue("@ShortName", "%{0}%")  でも出そうです。

    ネット等で、半日調べたのですが、だめでした。

    よろしくお願いします。

    YKsaila

    2012年5月1日 9:19
  • trapemiyaさんではありませんが.....。

    パラメータライズドクエリは、話のついでで出てきていますが

    当初の質問とはかけ離れた内容ですので、別途違うスレッドとして質問した方がいいように思います。

    また、個人宛に回答を求めるのも避けた方がよいと思います。

    他の方々からの回答を減らしてしまうでしょうし、広く共有された場所ですので。。

    ということで、本題。。。。

    「~{0}~」の構文は「String.Format」メソッド用の構文ですので、パラメータクエリとは切り離して考えてください。

    (String.Formatのヘルプを参照しましょう。)

    うまくいったコード(Jittaさんが回答してくださったコード)を見てみましょう。

    String.Formatメソッドには2つの引数が指定されています。

      第一引数・・・・SQLの文字列({0}が中に入っている...。)

      第二引数・・・・「SHN」変数

    です。

    これは、「第一引数の文字列(SQL)の{0}の個所に第二引数(SHNの値)を埋め込んで返しなさい。」という意味のプログラムです。

    では、今回エラーとなっているプログラムを見てみましょう。

    {0}の位置に第二引数(SHNの値)を入れようとしても{0}がありません。

    、、、、結果、エラーとなっちゃうわけです。

    2012年5月1日 12:28
  •  あおなでさんへ

    親切かつ丁寧なご忠告、ありがとうございました。 まだ、初心者で使用法については気をつけていたのですが。

    >当初の質問とはかけ離れた内容ですので、別途違うスレッドとして質問した方がいいように思います。

    たしかに、その一面もあり、どうしようか迷ったのですが。

    >また、個人宛に回答を求めるのも避けた方がよいと思います。 他の方々からの回答を減らしてしまうでしょうし、広く共有された場所ですので。

    そうなんですね、以後、気をつけたいと思います。

    さて、内容に関してですが;

    うーん、String.Formatの理解が不足していたようです。 助かりました。 ありがとうございます。

    で、下記のコードに書き換えましたら、うまくいきました。

    これですと、パラメーターは使ってない(?)ですが、SQL文の中に文字式はない(?)ので、SQLインジェクション攻撃は避けられるのでしょうか?

    でも、'%{1}%' が微妙かもしれないですね。

    以下、変更コードです(これは、正常に動きます):

        Dim FLG_Branch As Integer = 0
            Dim ShortName As String = SHN  '---別の個所で代入されるもの、Public SHN As String
            sqcmb = String.Format("SELECT T_M_Client.Client_ID, T_M_Client.ClientCode, T_M_Client.ShortName FROM T_M_Client " & _
                                        "Where FLG_Branch= {0} and ShortName Like '%{1}%' order by Kanacode", FLG_Branch, ShortName)

    YKsaila

    2012年5月1日 13:21
  • 結論から。。SQLインジェクション攻撃は避けられていません。

    SHNの値に何が入っているのかわかりませんが、ユーザーが直接入力できる値(または操作できる値)であれば

    回避できていない事になります。

    {1}に「';DELETE FROM T_M_Client ;~」とか入れられたらテーブルを全件削除されちゃいますよね。。。

    String.Formatを利用しても、文字列の連結を行っても、変数の値を直接SQL文字列に埋め込んでいることに変わりはありません。

    そのような方法では、ほとんどの場合、SQLインジェクションは回避できていません。

    パラメータクエリを利用した場合、単なる文字の置き換えではなく、制御文字などを適切に変換(エスケープ)してくれます。

    その結果、SQLインジェクション対策となります。

    また、SQLのコンパイルが事前に行われるため、パラメータが違うだけで同じSQLを何度も実行する場合など処理速度の向上が見込めます。。

    2012年5月1日 13:45
  • これですと、パラメーターは使ってない(?)ですが、SQL文の中に文字式はない(?)ので、SQLインジェクション攻撃は避けられるのでしょうか?

    避けられません。SQLインジェクションとは、攻撃者がパラメータの部分にある文字式を入れることにより、実行されるSQL文が本来とは違う命令を実行するよるに書き換えられてしまうことです。
    ですから、これを防ぐためには、攻撃者が入力した文字列をそのような攻撃的なSQL文にならないように無害化する必要があります。この無害化はサニタイズと言って、自分でも行うことができますが、パラメータライズドクエリを使うことによって自動的に行うことができますし、確実です。
    String.Formatはサニタイズの処理をしませんから、SQLインジェクションに成りえるわけです。
    パラメータライズドクエリに関しては、例えば以下の例が参考になります。

    ADO.NET のコード例
    http://msdn.microsoft.com/ja-jp/library/dw70f090.aspx

    何かついて調べようと思った場合は、キーワードを上手に使って検索しましょう。今回は、コード中に「sqlcommand parameters add」などが出てくるわけですから、それらを使ってコード例を探しましょう。見つけたらそれを真似し、そのコードをよく理解し、自分のものにしましょう。この繰り返しでプログラムが上達していきます。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年5月1日 14:05
    モデレータ
  • あおなでさん、trapemiyaさんへ

    ありがとうございました。

    パラメータライズドクエリについて、もっと学ぶ必要を痛感しました。

    YKsaila

    2012年5月1日 17:11