複数条件のプログラムを作りたい

タグの編集
投稿者 名無し  (社会人) 投稿日時 2014/1/30 09:28:14
初めて質問させていただきます。
宜しくお願いします。

今、vb2010でユーザーがTextboxに入力した条件を元にDataGridviewに検索結果を出すプログラムを作っていますが、検索結果をDataGridviewに出現させる処で躓いています。
上司からヒントとかを貰い、投稿者の私はプログラム自体が初めてな所もあるので基本的なミスがあるかもしれませんが返事を貰えると幸いです。

Imports System.Data.SqlClient

Public Class 生産者検索

Private Sub btnGo_Click(sender As System.Object, e As System.EventArgs) Handles btnGo.Click
        Dim wOK As Boolean
        Dim cnstr As String = "Data Source=user;Initial Catalog=データベース;Integrated Security=True"
        Dim sql As String
        sql = "SELECT * "
        sql += "FROM 生産者情報"
        Dim dt As New DataTable
        Dim da As New SqlDataAdapter(sql, cnstr)
        If TextBox1.Text.Length > 0 Then
            wOK = True
            If radio1B.Checked Then
                sql += " where (生産者番号 Like '%" & TextBox1.Text.Trim & "%')"
            Else
                sql += " WHERE (生産者番号 Like '" & TextBox1.Text.Trim & "%')"
            End If
        End If

        If TextBox2.Text.Length > 0 Then
            If radio2B.Checked Then
                If wOK = True Then
                    sql += " OR (生産者名 Like '%" & TextBox2.Text.Trim & "%')"
                Else
                    sql += " WHERE (生産者名 Like '%" & TextBox2.Text.Trim & "&')"
                End If
            Else
                If wOK = True Then
                    sql += " or (生産者名 Like '%" & TextBox2.Text.Trim & "%')"
                Else
                    sql += " WHERE (生産者名 LIke '" & TextBox2.Text.Trim & "&')"
                End If
            End If
            wOK = True
        End If

        If TextBox3.Text.Length > 0 Then
            If razio3B.Checked Then
                If wOK = True Then
                    sql += " OR (Rank Like '%" & TextBox3.Text.Trim & "%')"
                Else
                    sql += " WHERE (Rank Like '%" & TextBox3.Text.Trim & "&')"
                End If
            Else
                If wOK = True Then
                    sql += " OR (Rank Like '%" & TextBox3.Text.Trim & "%')"
                Else
                    sql += " WHERE (Rank LIke '" & TextBox3.Text.Trim & "&')"
                End If
            End If
        End If
        Try
            da.Fill(dt)
            DataGridView1.DataSource = dt 'DataGridview1にdtのデータを表示する
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class


・wOKはRadiobtnが一つだけ選択されているかの確認
・Radio1B,2B,3Bはあいまい検索にするか、先頭検索にするかの選択です
投稿者 an  (社会人) 投稿日時 2014/1/30 11:29:02
> 上司からヒントとかを貰い、

基本的には、近くに聞く人がいるのであれば、その人に聞くべきと思います。
ネット経由ではニュアンス等が伝わりにくい&時間がかかるので。


それはさておき、

> 検索結果をDataGridviewに出現させる処で躓いています。

どこでどう躓いているのでしょうか?
・コンパイルエラーが出る。
 →どこでどのような?
・実行時例外が発生する。
 →どこでどのような?
・思った結果が出ない。
 →どうなるつもりがどうなってしまう?
・etc・・・


環境がないので、試していませんが、ぱっと流し読みして気になった点を数点。
(1)
SQL文(SELECT文)を文字列構築していますが、
変数daのインスタンス生成の前後で構築しています。
前で基本的な構文、後で条件部分の構築をしているようですが、
これでは、条件構築しても、変数daのインスタンスには影響しないような気がします。
(要は、どのような入力を行っても、生産者情報テーブルの全件を取得している気がします。)
変数daのインスタンス生成は、位置的にはda.Fillの直前当たりにすべきではないでしょうか?


(2)
> sql += " WHERE (生産者名 Like '%" & TextBox2.Text.Trim & "&')"
「&」を利用されていますが、「%」の間違いではないでしょうか?
(DB環境が記載されていないため、間違いとは言い切れませんが、
 自分は聞いたことが無い気がします。)



ここからは今回の直接問題ではありませんが、個人的に気になった部分です。

(3)
SQL文の「WHERE」や「OR」が大文字のところがあったり、小文字のところがあったり、
また「Like」については先頭文字のみ大文字と、統一感がなく見辛いです。
(「LIke」というのもあります。)
どちらかに統一した方がいいと思います。
(一般的かどうかは分かりませんが、自分の携わったプロジェクトでは、
SQL文はすべて大文字に統一としたところが多いです。)


(4)
SQL文のように文字列を足しこみながら構築する場合、
String型よりStringBuilder型を使う方が一般的のようです。
参考: http://jeanne.wankuma.com/tips/vb.net/string/stringbuilder.html


(5)
SQL文に入力値が含まれる場合は直接文字列として使用すると、
セキュリティ的に問題(SQLインジェクション)があるので、パラメータ化すべき。
参考: http://www.kanaya440.com/contents/tips/vb/002.html


(6)
 
       If TextBox2.Text.Length > 0 Then
            If radio2B.Checked Then
                 If wOK = True Then
                     sql += " OR (生産者名 Like '%" & TextBox2.Text.Trim & "%')"
                 Else
                     sql += " WHERE (生産者名 Like '%" & TextBox2.Text.Trim & "&')"
                 End If
             Else
                 If wOK = True Then
                     sql += " or (生産者名 Like '%" & TextBox2.Text.Trim & "%')"
                 Else
                     sql += " WHERE (生産者名 LIke '" & TextBox2.Text.Trim & "&')"
                 End If
             End If
            wOK = True
       End If
 

とありますが、似たような処理、コードが多いです。
逆にいうと違いは、
・「OR」または「WHERE」
・頭に「%」をつけるかどうか
です
うまく記述すればコンパクトになります。
 
    If TextBox2.Text.Length > 0 Then
        If wOK = True Then
            sql += " OR "
        Else
            sql += " WHERE "
        End If

        sql += " (生産者名 Like '"
        If radio2B.Checked Then
            sql += "%"
        End If
        sql += TextBox2.Text.Trim & "&')"

        wOK = True
    End If
 

(上記(3)~(5)の指摘は考慮していません。)


とりあえず参考まで。
投稿者 るきお  (社会人) 投稿日時 2014/1/30 13:04:28
必須ではありませんが、個人的に気になる部分は
変数wOK と WHERE を結合するタイミングです。

wOKの意味がわかりにくく、プログラム全体の見通しが悪くなっています。

WHERE をくっつけるのは最後にしたほうがスマートになることが多いですよ。

下記はあくまでイメージですがこんな感じです。
Dim sqlBody As String
sqlBody = "SELECT * FROM 生産者情報"

Dim sqlWhere As New System.Text.StringBuilder 'Stringでも可能ですが。anさんの指摘を参照。 

If xxxx Then
    sqlWhere.AppendLine("A=1")
End If

If xxxx Then
    If sqlWhere.Length > 0 Then
        sqlWhere.Append(" OR ")
    End If
    sqlWhere.Append("B=1")
End If



Dim sql As String
sql = sqlBody & sqlWhere.ToString()


なお、パラメーター化クエリが使用可能であれば必ず使用します。
ただその説明を一緒に書くと論点がぼけるので、ここではパラメーター化クエリを使わないイメージとして紹介しました。
投稿者 名無し  (社会人) 投稿日時 2014/1/30 17:58:46
躓く所について詳しい説明を忘れていました。
言われた通りに検索条件を入れても全件表示されている状態です。
&についての指摘はこちらの入力ミスでした。
anさん、るきおさんの指摘通りにコードを修正しました

If TextBox1.Text.Length > 0 Then
            wOK = True
            If Radio1B.Checked Then
                sql += " where (生産者番号 Like '%" & TextBox1.Text.Trim & "%')"
            Else
                sql += " where (生産者番号 Like '" & TextBox1.Text.Trim & "%')"
            End If
        End If

        If TextBox2.Text.Length > 0 Then
            If wOK = True Then
                sql += " or "
            Else
                sql += " where "
            End If

            sql += " (生産者名 Like '"
            If Radio2B.Checked Then
                sql += "%"
            End If
            sql += TextBox2.Text.Trim & "&')"

            wOK = True
        End If

        If TextBox3.Text.Length > 0 Then
            If wOK = True Then
                sql += " or "
            Else
                sql += " where "
            End If

            sql += " (Rank Like '"
            If Radio3B.Checked Then
                sql += "%"
            End If
            sql += TextBox3.Text.Trim & "&')"
            wOK = True
        End If

        Dim da As New SqlDataAdapter(sql, cnstr)
        Try
            da.Fill(dt)
            DataGridView1.DataSource = dt 'DataGridview1にdtのデータを表示する
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

すると、生産者番号のみでの検索が可能になりましたが
生産者番号以外の条件を入力すると全件表示されなくなりました。

投稿者 魔界の仮面弁士  (社会人) 投稿日時 2014/1/30 18:44:26
実際には、「'」や「%」や「_」が入力された場合にも備える必要があります。

たとえば、テキストボックスに「100%」という文字列が指定された場合、
『100%ジュース』は抽出されるべきですが、『100円ジュース』は除外されるべきです。

Replace などを併用して加工しましょう。
「列名 LIKE '%int''l%'」          … "int'l" を含む文字列
「列名 LIKE '100\%%' ESCAPE '\'」 … "100%" で始まる文字列
「列名 LIKE '\\100%' ESCAPE '\'」 … "\100" で始まる文字列
「列名 LIKE '\100%'」             … "\100" で始まる文字列



> &についての指摘はこちらの入力ミスでした
指摘があったのは、「&」ではなく「&」についてです。
そしてその「&」については、未だに直っていないように見受けられます。


> sql += " where (生産者番号 Like '%" & TextBox1.Text.Trim & "%')"
間違いはありませんが、文字列結合に「+ 演算子」と「& 演算子」が混在しています。
文字列結合は「& 演算子」で統一しましょう。『sql &= …』のように。


> すると、生産者番号のみでの検索が可能になりましたが
> 生産者番号以外の条件を入力すると全件表示されなくなりました。
そのときの SQL がどうなっているか、確認されましたか?

たとえば、
 TextBox1.Text = "凄惨"
 Radio1B.Checked = True
 TextBox2.Text = "青酸"
 Radio2B.Checked = False
 TextBox3.Text = "楽"
 Radio3B.Checked = False
という条件の場合、提示いただいたコードは
 where (生産者番号 Like '%凄惨%') or  (生産者名 Like '青酸&') or  (Rank Like '%楽&')

になります。% と & の間違いということはありませんか?
投稿者 an  (社会人) 投稿日時 2014/1/31 11:16:04
> すると、生産者番号のみでの検索が可能になりましたが
> 生産者番号以外の条件を入力すると全件表示されなくなりました。

とありますが、前回の自分の投稿では

> > sql += " WHERE (生産者名 Like '%" & TextBox2.Text.Trim & "&')"
> 「&」を利用されていますが、「%」の間違いではないでしょうか?
> (DB環境が記載されていないため、間違いとは言い切れませんが、
> 自分は聞いたことが無い気がします。)

と記載しましたが、これが分かりにくい表現でしたね。

これに対して

> &についての指摘はこちらの入力ミスでした

とありますが、
こちらについては、魔界の仮面弁士さんが以下のようにフォローしてます。

> 指摘があったのは、「&」ではなく「&」についてです。
> そしてその「&」については、未だに直っていないように見受けられます。


> 「&」を利用されていますが
この「&」というのは、VBの文字列連結の「&」ではなく、
SQLの文字列曖昧比較を行う際の「Like」の右辺の文字列の「&」のことです。
「Like」直後の先頭を曖昧にするための記号は「%」で指定してますよね?
なのに、それに対して最後を曖昧にするための記号はなぜか「&」を指定しています。
[code]
sql += " WHERE (生産者名 Like '%" & TextBox2.Text.Trim & "&')" 'これだと前方ななんでも良くて、後方に「&」という文字が含まれるという意味になる。
sql += " WHERE (生産者名 Like '%" & TextBox2.Text.Trim & "%')" '前方後方なんでも良いになる。
                                                          ↑これ!
[/code]

(VBとSQLが混じった形でプログラムし、記号もそれぞれ意味を持つのでややこしいので、
 混同してしまう気持ちはよくわかります^^;)



> anさん、るきおさんの指摘通りにコードを修正しました

るきおさんの指摘が含まれていないような・・・。
るきおさんの指摘では
・変数wOKの存在意義
・ベースのSQLとWHERE句のSQLの変数の分割
・StringBuilderの使用(自分が省略した部分のフォローとして)
だったと思います。

もし、るきおさんの指摘通りやってみたけどうまくいかなかったというのであれば、
SQL文の最後に連結しているところで「WHERE」が抜けているからかもしれません。
Dim sql As String
sql = sqlBody & sqlWhere.ToString()

ここを
Dim sql As String
If sqlWhere.Length = 0 Then
    sql = sqlBody 
Else
    sql = sqlBody & " WHERE " & sqlWhere.ToString()
End If

こうするといいかもしれません。
最後に" WHERE "を付加する処理を行う事により、
途中での" WHERE "の処理がなくなり、コンパクトになります。


また、自分の指摘した個所は結構対応されていましたが、
追加でもう一点。
「生産者番号」の条件を設定するIf文の部分ですが、
よく見ると、前回指摘した「生産者名」の部分と一部同じようなロジックに
見えませんか?
こちらもコンパクトにできるでしょう。
投稿者 るきお  (社会人) 投稿日時 2014/1/31 12:53:43
>もし、るきおさんの指摘通りやってみたけどうまくいかなかったというのであれば、
>SQL文の最後に連結しているところで「WHERE」が抜けているからかもしれません。
WHEREを抜かしていました…。
フォローありがとうございます。

私の記載は本質的ではないので、余力がでてきたら参考にされるので良いと思います。
投稿者 an  (社会人) 投稿日時 2014/1/31 14:15:23
コード表示に失敗していたので修正&再掲載



'これだと前方ななんでも良くて、後方に「&」という文字が含まれるという意味になる。 
sql += " WHERE (生産者名 Like '%" & TextBox2.Text.Trim & "&')"
                                                         '↑これ!この「&」を 

'これで前方後方なんでも良いになる。 
sql += " WHERE (生産者名 Like '%" & TextBox2.Text.Trim & "%')" 
                                                         '↑これ!「%」にする必要あり 

投稿者 名無し  (社会人) 投稿日時 2014/1/31 17:42:00
  If TextBox1.Text.Length > 0 Then
            wOK = True
            If Radio1B.Checked Then
                sql += " where (生産者番号 Like '%" & TextBox1.Text.Trim & "%')"
            Else
                sql += " WHERE (生産者番号 Like '" & TextBox1.Text.Trim & "%')"
            End If
        End If

        If TextBox2.Text.Length > 0 Then
            If wOK = True Then
                sql += " OR "
            Else
                sql += " WHERE "
            End If

            sql += " (生産者名 Like '"
            If Radio2B.Checked Then
                sql += "%"
            End If
            sql += TextBox2.Text.Trim & "%')"

            wOK = True
        End If

        If TextBox3.Text.Length > 0 Then
            If wOK = True Then
                sql += " OR "
            Else
                sql += " WHERE "
            End If

            sql += " (Rank Like '"
            If Radio3B.Checked Then
                sql += "%"
            End If
            sql += TextBox3.Text.Trim & "%')"
            wOK = True
        End If

        Dim da As New SqlDataAdapter(sql, cnstr)
        Try
            da.Fill(dt)
            DataGridView1.DataSource = dt 'DataGridview1にdtのデータを表示する
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class

今回はあまり時間がなく少ししか手直し出来ませんでした。
それでも、anさん、仮面弁士さんの指摘通りに修正をしたら生産者番号以外でも条件を指定しての検索が出来ました。
有難うございました。
るきおさんのコードですが、すみません。作ってみたんですが良く分かりませんでした。

ここで疑問に思ったんですが、wOKやRadiobtnなどを使わずにTextboxのみでデータベースの複数条件の作ることは可能でしょうか?
投稿者 daive  (社会人) 投稿日時 2014/2/1 11:39:31
>ここで疑問に思ったんですが、wOKやRadiobtnなどを使わずに
>Textboxのみでデータベースの複数条件の作ることは可能でしょうか? 
私の、表現が適当でない可能性がありますが。
例えば、
1.可能か不可能か、
  可能です。
2.実用になるかならないか、
  要件次第です。
  SELECTから始まる文字列を、操作者が間違えずに入れられるのか?
  SQL インジェクションやSQL インジェクション 対策 について調べてみてください。
3.質問者さんは、今何を行っているのか?
  たぶん、SQL用のクエリを作っているはずです。
>Dim da As New SqlDataAdapter(sql, cnstr)
>(中略)
>DataGridView1.DataSource = dt 'DataGridview1にdtのデータを表示する
  プログラムから、データベースの機能を呼して、
  結果を、DataGridView へ表示している様子です。
  sql:クエリ文字列
  cnstr:データベース接続文字列
  になっているようですが?
  SqlDataAdapter について、調べてみてください。

  MS-SQL Server 2005 以後であれば、
  SQL Server Management Studio
  が、データベースの、管理ツールです。
  管理ツールを使う事により、データベースの作成、
  テーブルの変更、確認
  種々権限の設定、
  クエリ、ストアドや、パラメータクエリ(パラメタライズドクエリ)
  の作成、確認ができます。
投稿者 an  (社会人) 投稿日時 2014/2/3 10:38:37
> 今回はあまり時間がなく少ししか手直し出来ませんでした。
> それでも、anさん、仮面弁士さんの指摘通りに修正をしたら生産者番号以外でも条件を指定しての検索が出来ました。

メインの質問は、思った通りに動かないということなので、
それ以外の自分が気になった点については、
ぶっちゃけ直さなくても大きな問題はないので、最悪直さなくてもいいと思います。
ただ、後で見るときに(質問者さん自身および他の人も含め)、
より分かりやすいソースコードになっている方が良いと思いますので、
心に留めておいていただけたら・・・と思います。



> ここで疑問に思ったんですが、wOKやRadiobtnなどを使わずにTextboxのみでデータベースの複数条件の作ることは可能でしょうか? 

これについては、daiveさんも回答されていますので、補足まで。

「wOK」と「Radiobtn」で内容がだいぶ異なります。
「wOK」については内部的な話であり、ある程度自由度が高いと思います。
「Radiobtn」については外部的な話であり、使う人がどうしてほしいかが重要になると思います。

まず「wOK」についてですが、これはるきおさんのコード(2014/1/30 13:04:28 投稿)が参考になりますが、
> るきおさんのコードですが、すみません。作ってみたんですが良く分かりませんでした。
との事なので、これを理解すれば良いと思います。
何がどう分からなかったのかが分からないので、何とも言いにくいですが、軽く説明しますと、
るきおさんのコードをみると「wOK」がありません。
「wOK」の代わりにWHERE句専用のSQL文を格納する変数(「sqlWhere」)があり、
その変数に値が既に設定されているかどうかで、「wOK」の代わりとしています。
sqlWhereはStringBuilder型で宣言されていますので、
使用方法についてはヘルプを参照してください。

次に「Radiobtn」についてですが、
仮に、この「Radiobtn」をなくして、今と同じ検索ができるようにするにはどうすれば良いでしょうか?
例としては
「プログラム側では「%」の設定を一切しないで、必要に応じて使用者に「%」を入力してもらう」
という形があると思います。
ここで問題なのは daive さんが言っている「実用になるかならないか」だと思います。
上記例の場合、使用する人に、説明しなければなりませんし、覚えてもらわなければなりません。
それが「Radiobtn」なら視覚的にも日本語的にも分かる内容にできるので、
使用者側にはメリットが多くなると思います。
ただ気になるのは「%」という文字を検索したいときはどうなるでしょうか?
この問題については質問者さんが最後に提示したソースコードにも言えますが、
それらも考慮して使用者に説明するのは、使用者が混乱するだけだと思います。
これに関しては、魔界の仮面弁士さんの投稿(2014/1/30 18:44:26)を参照してください。


結構、省略して説明したので、分かりにくかったかもしれませんので、
分からなかった箇所がありましたら、具体的に質問してみてください。
投稿者 名無し  (社会人) 投稿日時 2014/2/5 15:40:47
Private Sub btnGo_Click(sender As System.Object, e As System.EventArgs) Handles btnGo.Click
        Dim wOK As Boolean
        Dim cnstr As String = "Data Source=DENSAN09;Initial Catalog=データベース;Integrated Security=True"
        Dim sql As String
        sql = "SELECT * "
        sql += "FROM 生産者"
        Dim dt As New DataTable

        If TextBox1.Text.Length > 0 Then
            wOK = True
            If あいまい検索1A.Checked Then
                sql += " WHERE (生産者番号 Like '%" & TextBox1.Text.Trim & "%')"
            Else
                sql += " WHERE (生産者番号 Like '" & TextBox1.Text.Trim & "%')"
            End If
        End If

        If TextBox2.Text.Length > 0 Then
            If wOK = True Then
                sql += " OR "
            Else
                sql += " WHERE "
            End If

            sql += " (生産者名 Like '"
            If あいまい検索2B.Checked Then
                sql += "%"
            End If
            sql += TextBox2.Text.Trim & "%')"

            wOK = True
        End If

        If TextBox3.Text.Length > 0 Then
            If wOK = True Then
                sql += " OR "
            Else
                sql += " WHERE "
            End If

            sql += " (Rank Like '"
            If あいまい検索3B.Checked Then
                sql += "%"
            End If
            sql += TextBox3.Text.Trim & "%')"
            wOK = True
        End If

        Dim da As New SqlDataAdapter(sql, cnstr)
        Try
            da.Fill(dt)
            DataGridView1.DataSource = dt 'DataGridview1にdtのデータを表示する
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class

※本来、あいまい検索は半角や大文字などを区別しない検索方法ですが、ここではあいまい検索にチェックが付くと入力された単語さえあれば、単語の位置とか関係なくDataGridviewに表示させる方法になっています。

※RadiobtnBにはあいまい検索、Aには先頭検索となっています。

質問した時と比べて大分検索プログラムの形になりつつありますが、複数の条件を記入したとしても一番最初に来た検索条件の結果のみDatagridviewに表示されています。
仕様としては複数の条件を全てあったデータだけを取りたいのですがどうすれば良いのでしょうか?

anさん
内部的な話はプログラムを作成者目線、外交的な話はプログラムの利用者目線の意味合いとして宜しいでしょうか?
るきおさんのコードについてですが、

  Dim cnstr As String = "Data Source=DENSAN09;Initial Catalog=データベース;Integrated Security=True"
        Dim SqlBody As String
        SqlBody = "SELECT * FROM 生産者情報"
        Dim sqlWhere As New System.Text.StringBuilder


        Dim sql As String
        If TextBox1.Text = 0 Then
            sql = SqlBody
        Else
            sql = SqlBody & " WHERE " & sqlWhere.ToString()
        End If

まで作れましたが、if xxx から何を打ち込んだら良いのか分からずいます。
今は、データ検索の高速化とかは考えずに検索プログラムの作成を目標にしています
投稿者 (削除されました)  () 投稿日時 2014/2/5 15:41:58
(削除されました)
投稿者 an  (社会人) 投稿日時 2014/2/5 16:49:57

> 質問した時と比べて大分検索プログラムの形になりつつありますが、
> 複数の条件を記入したとしても一番最初に来た検索条件の結果のみDatagridviewに表示されています。

この「一番最初に来た検索条件の結果のみ」という意味がよくわかりませんが、
とりあえず、まずはデバッグしてみましょう。
VB側がいけないのかSQLがいけないのかを特定すべきだと思います。
なので、SQL文を実行する箇所の直前(Dim da As New SqlDataAdapter(sql, cnstr))に
以下のコードを1行追加してみてください。

    MessageBox.Show(sql)

これで実行されるSQLが表示されますので、
複数の条件を入力した状態で実行して、
まずはそれが正しいかを判断してください。
(ちなみにMsgBoxで表示された内容はCtrl+Cでコピーできますので、
 見やすいエディタにコピーしてから確認すると楽です。)
必要に応じて、そのSQL文をVBを通さないで他のツールから実行してみてください。
そこでおかしいようであれば、まずはどういったSQL文を作成すれば良いか、
修正してみると良いでしょう。


> 仕様としては複数の条件を全てあったデータだけを取りたいのですがどうすれば良いのでしょうか?

複数の条件が全てあったレコードを抽出するには、各条件を「AND」でつなげる必要がありますが、
現在は「OR」になっています。
これでは、どれかに一致したものが表示されます。
全ての条件に一致するレコードのみを出力したければ、各条件を「AND」でつなげましょう。
(SQLの基本的事項なので参考書等で確認することをお勧めします。)
(さらに条件という観点でいうとSQLだけに限らず、プログラムの基本になります。)


> anさん
> 内部的な話はプログラムを作成者目線、外交的な話はプログラムの利用者目線の意味合いとして宜しいでしょうか?

基本的にはその通りです。
(ん?外交?^^;)


> るきおさんのコードについてですが、
> ~中略~
> まで作れましたが、if xxx から何を打ち込んだら良いのか分からずいます。

るきおさんもおっしゃってますが、必須な内容ではないので、
今回の件はまずは置いといて、
他の部分が正常に動作してから考えましょう。
(自分も無関係な部分や余計なツッコミを入れてしまったのが悪いのですが・・・。)
投稿者 (削除されました)  () 投稿日時 2014/2/7 10:24:02
(削除されました)
投稿者 社会人  (社会人) 投稿日時 2014/2/7 10:25:14
Private Sub btnGo_Click(sender As System.Object, e As System.EventArgs) Handles btnGo.Click
        Dim wOK As Boolean
        Dim cnstr As String = "Data Source=データベース;Initial Catalog=データベース;Integrated Security=True"
        Dim sql As String
        sql = "SELECT * "
        sql += "FROM 生産者"
        Dim dt As New DataTable

        If TextBox1.Text.Length > 0 Then
            wOK = True
            If あいまい検索1A.Checked Then
                sql += " WHERE (生産者番号 Like '%" & TextBox1.Text.Trim & "%')"
            Else
                sql += " WHERE (生産者番号 Like '" & TextBox1.Text.Trim & "%')"
            End If
        End If

        If TextBox2.Text.Length > 0 Then
            If wOK = True Then
                sql += " AND "
            Else
                sql += " WHERE "
            End If

            sql += " (生産者名 Like '"
            If あいまい検索2B.Checked Then
                sql += "%"
            End If
            sql += TextBox2.Text.Trim & "%')"

            wOK = True
        End If

        If TextBox3.Text.Length > 0 Then
            If wOK = True Then
                sql += " AND "
            Else
                sql += " WHERE "
            End If

            sql += " (Rank Like '"
            If あいまい検索3B.Checked Then
                sql += "%"
            End If
            sql += TextBox3.Text.Trim & "%')"
            wOK = True
        End If

        Dim da As New SqlDataAdapter(sql, cnstr)
        Try
            da.Fill(dt)
            DataGridView1.DataSource = dt 'DataGridview1にdtのデータを表示する
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class

anさんの指摘通りにANDに変更したら欲しい結果になりました。
段々と完成形に近づいていますが、もう少し皆さんの協力をお願いします。
外交的な話は外向的な話の間違いです。

生産者番号を検索する際に、00~10のデータ11件欲しい場合など範囲指定検索のコードを考えているんですが思いつきません。

自分なりに考え、範囲指定検索する箇所にはTextBoxを二つ置き、両方に記入があった場合のみ実行するコード作った結果はエラーで弾かれました。

 If TextBox1.Text.Length > 0 And TextBox2.Text.Length > 0 Then
            wOK = True
            If RadioB.Checked Then
                sql += " AND "
            Else
                sql += " WERE "
            End If
End If

弾かれたというより、どうすれば良いのか分からないというのが現状です。
ネットとかでも調べても中々欲しい情報が見つからないので宜しくお願いします 
投稿者 an  (社会人) 投稿日時 2014/2/7 10:59:57
> anさんの指摘通りにANDに変更したら欲しい結果になりました。
> 段々と完成形に近づいていますが、もう少し皆さんの協力をお願いします。

それは何よりです。

> 結果はエラーで弾かれました。

エラーがあった場合は、まずはそのエラーが発生した場所(行)と
そのエラー(メッセージ等)を提示しましょう。

それはさておき、
まず、基本的な考え方として、VB上でSQLという違う言語を取り扱っている場合、
VBの問題なのかSQLの問題なのかを判断する必要があります。
(今回の例に限らずエラー・障害・etc・・・等の時はまず原因の特定が必要です。)

コンパイルが通っていて動作するというのであれば、SQL実行前のSQL文を出力し、
そのSQLが構文として正当かどうか確認してください。
(前回のMessageBoxの方法でもなんでも良いです。)


> If TextBox1.Text.Length > 0 And TextBox2.Text.Length > 0 Then
> ~中略~
> 弾かれたというより、どうすれば良いのか分からないというのが現状です。

コードを確認したところ、SQL文を構築する際に、TextBox1等の値をSQL文に加えておらず、
SQL文が中途半端な状態だからだと思います。
「どうすれば良いのか分からないというのが現状」といったところで、
中途半端な状態で動かしてもエラーが起きてもしょうがないかと。
動作させるには最低限のSQL文の構築が必要です。



> 生産者番号を検索する際に、00~10のデータ11件欲しい場合など範囲指定検索のコードを考えているんですが思いつきません。
> ~中略~
> ネットとかでも調べても中々欲しい情報が見つからないので宜しくお願いします 

今回は範囲指定検索を行いたいとのことで、
「SQL 範囲指定」でGoogleで検索したところ、
今回使用できるであろう情報がたくさんヒットしましたが、
これらは使えないのでしょうか?
使えないのであれば、どういったところに問題があるのか
詳しく説明していただけたら、と思います。

投稿者 社会人  (社会人) 投稿日時 2014/2/7 16:11:11
If TextBox1.Text.Length > 0 And TextBox2.Text.Length > 0 Then
            If wOK = True Then
                sql += " WHERE (生産者コード Between '" & TextBox1.Text.Trim & "%' and '%" & TextBox2.Text.Trim & "%')"
            Else
                If TextBox1.Text.Length > 0 Then
                    wOK = True
                    If RadioB.Checked Then
                        sql += " WHERE (生産者コード Like '%" & TextBox1.Text.Trim & "%')"
                    Else
                        sql += " WHERE (生産者コード Like '" & TextBox1.Text.Trim & "%')"
                    End If
                End If

                If TextBox2.Text.Length > 0 Then
                    If wOK = True Then
                        sql += " AND "
                    Else
                        sql += " WHERE "
                    End If
                    sql += " (生産者コード Like '"
                    If RadioB.Checked Then
                        sql += "%"
                    End If
                    sql += TextBox2.Text.Trim & "%')"
                    wOK = True
                End If
            End If
        End If

エラーの文面みたら、単純な入力ミスによるエラーでした。
前回同様、Messageboxで検索結果の式を確認したら、Textbox2に何も反応していないので自分が入力した範囲が正常に動いていない可能性が高いです。
SQL 範囲指定で、Betweenが一番適していると思い早速打ち込んでみましたがうんともすんとも言いません。
サイトにあった SELECT  *  FROM  商品表 WHERE  単価 BETWEEN 100 AND 1900 を参考にしましたが良く分かりません。
投稿者 an  (社会人) 投稿日時 2014/2/7 18:36:25
> sql += " WHERE (生産者コード Between '" & TextBox1.Text.Trim & "%' and '%" & TextBox2.Text.Trim & "%')"

「BETWEEN」とLIKEのワイルドカード(「%」)は混同できないからだと思います。

まずは、VB上ではなく、SQLだけを実行するツールの方で
SQLが正常に動作するかを確認した方がよいと思います。

他にも提示されたプログラムはおかしいところがありそうですが、
取り急ぎBETWEENについてだけ。

(名前が変わっているけど質問者さんは同じ?)
投稿者 daive  (社会人) 投稿日時 2014/2/8 20:09:21
>SQLだけを実行するツールの方で
例えば、
1.MS-SQL Server 2000 : Enterprise Manager
2.MS-SQL Server 2005以後:SQL Server Management Studio
3.MySQL :MySQL workbench 、日本語版の提供が無い様子。英語版でも、困る事は少ない。
4.Oracle :Oracle SQL Developer 

DBの専門の方々は、コマンドラインツール(CUIツール)がお好みの方もいらっしゃいます。
私は、出来るだけ楽がしたいので、GUIツールの方が、好みです。
場合によっては、GUIツールからでは、設定出来ない機能があったりもします。
⇒SQL Server Management Studioで、メモリ使用量を小さくしすぎて、GUIツールが
 起動しなくなった場合は、コマンドラインツールから。
 MS-SQL Server では、各インスタンス毎の、メモリ使用量設定は、必須。
 初期値:OS毎の、最大メモリ量になっているので、下手なクエリで、全使用可能メモリを食いつぶす。
 この恐ろしい仕様を、知らない方は、皆さん嵌っています(私含む)。

MS-SQL Server に於いては、DMO / SMO の境界が、MS-SQL Server 2005 
DB情報、メタデータコレクション、スキーマ情報なども、MS-SQL 2000 / 2005 が境界で、
異なっている部分が多い様子。

各ツールは、各々初期設定等が必須。
特に、SQL Server Management Studio は、
独特の癖があるので、設定を理解して使用する
必要があります。(テーブルの修正、クエリの結果件数の指定、タブ右クリック機能など)

拡張子:udl での、機能
Data Source ODBC の、32ビット/64ビット の使い分け
なども、知っておくと、楽が出来る場面もあります。

読み物として、DBを扱う方に、まず読んでいただくのが、
「ミック:リレーショナル・データベースの世界」
 http://www.geocities.jp/mickindex/database/idx_database.html
 書籍化もされています。
投稿者 an  (社会人) 投稿日時 2014/2/10 13:47:57
> エラーの文面みたら、単純な入力ミスによるエラーでした。

どのような単純な入力ミスでしたか?
今後、ここを見た方にも参考になるように
また、回答者の皆さんがこの後も回答しやすいよう、
具体的に提示していただけたらと思います。


> 前回同様、Messageboxで検索結果の式を確認したら、
> Textbox2に何も反応していないので自分が入力した範囲が正常に動いていない可能性が高いです。

これはどういった意味でしょうか?
(検索結果の式?結果ではなく検索用のSQL文のこと?)
(Textbox2に何も反応していない?Textbox2に関するSQL文が構築されてない?)
「正常に動いていない可能性」については、何を持って正常というのかが、なんとも言えないので、
具体的に、画面にどのように入力したら、どのようにMessageboxに表示されたのかを
提示していただけたらと思います。
(たぶん、プログラムは記述された通り正常に動作しており、記述が間違っていると思います・・・。)

> S QL 範囲指定で、Betweenが一番適していると思い早速打ち込んでみましたがうんともすんとも言いません。

「うんともすんとも言わない」というのはどういう状況でしょうか?
・処理がそもそも動かない
・処理した結果が0件
・その他
このような場(直接隣にいるわけではない)では曖昧な表現は伝わりにくいので、
具体的に記載するようお願いします。


> サイトにあった SELECT  *  FROM  商品表 WHERE  単価 BETWEEN 100 AND 1900 を参考にしましたが良く分かりません。 
 
何がどう分からないのでしょうか?

上記のSELECT文の場合、
単価が100から1900のものが抽出されますので、
例えば99や1901のものは抽出されません。
今回のケースですと、「00」から「10」のものを抽出するのであれば、
WHERE 生産者コード BETWEEN '00' AND '10'
となれば、「03」や「10」等が抽出できるはずです。




> daive さん

フォローありがとうございます。
自分は環境面が詳しくなく、また環境が提示されていないので、
あまり嘘を書いちゃいけないと思って、その辺は細かく書きませんでした。


投稿者 名無し  (社会人) 投稿日時 2014/2/12 11:15:13
金曜日の発言の社会人は名前の入力ミスでした。
現在、こういったコードになっています。

Private Sub btnGo_Click(sender As System.Object, e As System.EventArgs) Handles btnGo.Click
        Dim wOK As Boolean
        Dim cnstr As String = "Data Source=DENSAN09;Initial Catalog=データベース;Integrated Security=True"
        Dim sql As String
        sql = "SELECT * "
        sql += "FROM 生産者情報"
        Dim dt As New DataTable

        If TextBox1.Text.Length >= 0 Then
            If TextBox2.Text.Length >= 0 Then
                wOK = True
                sql += " WHERE (生産者番号 between '%" & TextBox1.Text.Trim & "%' and '%" & TextBox2.Text.Trim & "%')" 
            Else
                wOK = True
                If RadioB.Checked Then
                    sql += " WHERE (生産者番号 Like '%" & TextBox1.Text.Trim & "%')"
                Else
                    sql += " WHERE (生産者番号 Like '" & TextBox1.Text.Trim & "%')"
                End If
            End If
        End If

        If TextBox3.Text.Length > 0 Then
            If wOK = True Then
                sql += " AND "
            Else
                sql += " WHERE "
            End If
            sql += " (生産者名 Like '"
            If RadioB.Checked Then
                sql += "%"
            End If
            sql += TextBox3.Text.Trim & "%')"
            wOK = True
        End If

        If TextBox4.Text.Length > 0 Then
            If wOK = True Then
                sql += " AND "
            Else
                sql += " WHERE "
            End If
            sql += " (Rank Like '"
            If RadioB.Checked Then
                sql += "%"
            End If
            sql += TextBox4.Text.Trim & "%')"
            wOK = True
        End If

        Dim da As New SqlDataAdapter(sql, cnstr)
        MessageBox.Show(sql)
        Try
            da.Fill(dt)
            DataGridView1.DataSource = dt 'DataGridview1にdtのデータを表示する
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class

前回のエラーについてなんですが、
 If TextBox1.Text.Length > 0 And TextBox2.Text.Length > 0 Then
            wOK = True
            If RadioB.Checked Then
                sql += " AND "
            Else
                sql += " WERE "
            End If

If TextBox1.Text.Length > 0 and TextBox2.Text.Length > 0 Then
                    wOK = True
                    If RadioB.Checked Then
                        sql += " WHERE (生産者コード Like '%" & TextBox1.Text.Trim & "%')"
                    Else
                        sql += " WHERE (生産者コード Like '" & TextBox1.Text.Trim & "%')"
                    End If
に変更する事で一応出来ました。

(生産者コードの00~10には全てデータが入っていると仮定しています)

うんともすんとも言わない状況ですが、
・Textboxに入力しても検索結果では 「SELECT * FROM 生産者 WHERE (生産者番号 BETWEEN '%00%' and '%10%')と表示れますがDataGrdiviewには一つもデータが表示されません。
・試しに sql += " WHERE (生産者コード between '00' and '10')"にすると00~10の11件のデータが表示されました。
という状況になっていまして。
更に
・最初の分岐が上手く行かず、Text1,2の両方が入力していないのに「SELECT * FROM 生産者 WHERE (生産者番号 BETWEEN '%%' and '%%')」となり、他の検索条件にまで到達しない状況になっている

と、ややこしい事になっています。
最初の分岐はandでも作ってみましたが同じ結果となりました。
以下がそのコードです。
If TextBox1.Text.Length >= 0 And TextBox2.Text.Length >= 0 Then
中の sel +=は一緒の為省きます。
End If

daiveさん
サイトの紹介有難うございます。
投稿後に見ます。
投稿者 名無し  (社会人) 投稿日時 2014/2/12 11:17:47
金曜日の発言の社会人は名前の入力ミスでした。
現在、こういったコードになっています。

Private Sub btnGo_Click(sender As System.Object, e As System.EventArgs) Handles btnGo.Click
        Dim wOK As Boolean
        Dim cnstr As String = "Data Source=DENSAN09;Initial Catalog=データベース;Integrated Security=True"
        Dim sql As String
        sql = "SELECT * "
        sql += "FROM 生産者情報"
        Dim dt As New DataTable

        If TextBox1.Text.Length >= 0 Then
            If TextBox2.Text.Length >= 0 Then
                wOK = True
                sql += " WHERE (生産者番号 between '%" & TextBox1.Text.Trim & "%' and '%" & TextBox2.Text.Trim & "%')" 
            Else
                wOK = True
                If RadioB.Checked Then
                    sql += " WHERE (生産者番号 Like '%" & TextBox1.Text.Trim & "%')"
                Else
                    sql += " WHERE (生産者番号 Like '" & TextBox1.Text.Trim & "%')"
                End If
            End If
        End If

        If TextBox3.Text.Length > 0 Then
            If wOK = True Then
                sql += " AND "
            Else
                sql += " WHERE "
            End If
            sql += " (生産者名 Like '"
            If RadioB.Checked Then
                sql += "%"
            End If
            sql += TextBox3.Text.Trim & "%')"
            wOK = True
        End If

        If TextBox4.Text.Length > 0 Then
            If wOK = True Then
                sql += " AND "
            Else
                sql += " WHERE "
            End If
            sql += " (Rank Like '"
            If RadioB.Checked Then
                sql += "%"
            End If
            sql += TextBox4.Text.Trim & "%')"
            wOK = True
        End If

        Dim da As New SqlDataAdapter(sql, cnstr)
        MessageBox.Show(sql)
        Try
            da.Fill(dt)
            DataGridView1.DataSource = dt 'DataGridview1にdtのデータを表示する
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class

前回のエラーについてなんですが、
 If TextBox1.Text.Length > 0 And TextBox2.Text.Length > 0 Then
            wOK = True
            If RadioB.Checked Then
                sql += " AND "
            Else
                sql += " WERE "
            End If

If TextBox1.Text.Length > 0 and TextBox2.Text.Length > 0 Then
                    wOK = True
                    If RadioB.Checked Then
                        sql += " WHERE (生産者コード Like '%" & TextBox1.Text.Trim & "%')"
                    Else
                        sql += " WHERE (生産者コード Like '" & TextBox1.Text.Trim & "%')"
                    End If
に変更する事で一応出来ました。

(生産者コードの00~10には全てデータが入っていると仮定しています)

うんともすんとも言わない状況ですが、
・Textboxに入力しても検索結果では 「SELECT * FROM 生産者情報 WHERE (生産者番号 BETWEEN '%00%' and '%10%')と表示れますがDataGrdiviewには一つもデータが表示されません。
・試しに sql += " WHERE (生産者コード between '00' and '10')"にすると00~10の11件のデータが表示されました。
という状況になっていまして。
更に
・最初の分岐が上手く行かず、Text1,2の両方が入力していないのに「SELECT * FROM 生産者情報 WHERE (生産者番号 BETWEEN '%%' and '%%')」となり、他の検索条件にまで到達しない状況になっている

と、ややこしい事になっています。
最初の分岐はandでも作ってみましたが同じ結果となりました。
以下がそのコードです。
If TextBox1.Text.Length >= 0 And TextBox2.Text.Length >= 0 Then
中の sel +=は一緒の為省きます。
End If

daiveさん
サイトの紹介有難うございます。
投稿後に見ます。
投稿者 名無し  (社会人) 投稿日時 2014/2/12 11:20:20

同じコードが二回投稿されていますが、15分の書き込みにミスがあるので17分の書き込みが正しいコードとなっています。
投稿者 an  (社会人) 投稿日時 2014/2/12 11:39:00
前回も記載しましたが、BETWEEN時の「%」は不要(というか今回はあってはダメ)で、

> ・試しに sql += " WHERE (生産者コード between '00' and '10')"にすると00~10の11件のデータが表示されました。

とのことですので、これは適用させてください。


> ・最初の分岐が上手く行かず、Text1,2の両方が入力していないのに
> 「SELECT * FROM 生産者情報 WHERE (生産者番号 BETWEEN '%%' and '%%')」となり、
> 他の検索条件にまで到達しない状況になっている
>
> と、ややこしい事になっています。

とありますが、「WHERE (生産者番号 BETWEEN ~」を付加する処理へ到達する条件を確認すると
> If TextBox1.Text.Length >= 0 Then
となっています。
「>=」では0以上(0を含む)なので、入力されていない(Length=0)時も
そちらの処理が行われるのでしょう。




以前も書きましたが、「プログラムは記述された通り正常に動作する」ものなので、
どういった動作をするのかという事がわかり、それとソースコードをにらめっこすれば、
ある程度あたりは付けれると思います。
しかも前回は「>」で処理していたのに、今回「>=」に変更されていますので、
その辺も加味すれば、さらにあたりが付け易いと思います。

また、デバッガによるデバッグ(ライン実行等)は行えてるのでしょうか?
デバッグ作業がきっちり行えないと今後も苦労すると思います。
(今後もこのような場で質問できるとは限らないので。)


投稿者 名無し  (社会人) 投稿日時 2014/2/14 16:02:00
anさん
ヒント有難うございます。

If TextBox1.Text.Length > 0 And TextBox2.Text.Length > 0 Then
                wOK = True
                sql += " WHERE (生産者番号 between " & TextBox1.Text.Trim & " and " & TextBox2.Text.Trim & ")"
end if

にした事で欲しい結果が出るようになりました。

しかし、データベースには登録日時という項目があり、それも検索条件の一部に入っています。
年月日を入力するだけで、入力範囲のデータを表示させたいのですが↑のコードを使っても出来ませんでした。
調べてみたら、Betweenでは出来ない。年月日何時何分何秒まで正確に入力しないといけない。などの条件は分かりましたが、ソースコードを組めません。
ご指導の程宜しくお願いします。

今回の件でデバッグ作業の重要性を痛感しました。
ソースコードの実力とデバッグ作業の実力の両方が無いとキツイです。
投稿者 HiDE-Ada  (社会人) 投稿日時 2014/2/15 17:52:46
回答がつかないようなので、中途半端ですがヒントを
Datetime型と思われる登録日時でも基本は同じbetweenが使えないわけではないです。
つまり
登録日時 between '2013/04/01' and '2014/03/30'
とすると、
2013/04/01 00:00:00:000~2014/03/30 00:00:00.000
が検索できると思います…
でも、後ろが00:00:00.000では問題なので
登録日時 between '2013/04/01' and '2014/03/30 23:59:59.999'
とできればよさそうです。

実際の検索で秒まで指定して検索したいのか?
それとも年月日だけで済ませたいのか?
あるいはある1日だけを指定することもあるのか?
でかわってきます。
登録日時 = '2014/01/01'
では、'2014/01/01 00:00:00.000'に一致するものだけしか
検索できないようなので、1日であっても
登録日時 between '2014/01/01' and '2014/01/01 23:59:59.999'
となるように、日付の後ろに'23:59:59.999'を付加すればよいと思います。

まぁ秒以下がめんどうなので、あるサイトでは
登録日時 >= '2014/01/01' AND 登録日時 < '2014/01/02'
として、次の日(当然計算が必要ですが)より前を条件とする
書き方を紹介してました。

SQLServerならCONVERT関数を使って
CONVERT(NVARCHAR, 登録日時, 111) = '2014/01/02'

CONVERT(NVARCHAR, 登録日時, 111) between '2014/01/02' and '2014/01/31'
という書き方ができなくもないですが、レスポンスを気にする場合は
カラムを関数処理することは反対されると思います。
ちなみに111はYYYY/MM/DD、11ならYY/MM/DDです。

プログラムはこんな問題ばかりなので、もっと検索して回答を
見つけられるようになりましょう。
「SQLServer 検索 日付」で検索するといっぱい見つかります。
http://chaichan.lolipop.jp/vbtips/VBMemo2006091302.htm
投稿者 an  (社会人) 投稿日時 2014/2/17 12:03:16
> しかし、データベースには登録日時という項目があり、それも検索条件の一部に入っています。
> 年月日を入力するだけで、入力範囲のデータを表示させたいのですが↑のコードを使っても出来ませんでした。
> 調べてみたら、Betweenでは出来ない。年月日何時何分何秒まで正確に入力しないといけない。などの条件は分かりましたが、ソースコードを組めません。

まずはじめに、
「↑のコードを使っても出来ませんでした。」とのことですが、
出来ないというのは、どう出来なかったのでしょうか

・コンパイル時にエラーが発生して実行できない。
 →どのようなプログラムで、どのようなエラーがどこで発生してる?
・実行時にエラーが発生して正常終了しない。
 →どのようなプログラムでどのような入力をしたら、どのようなエラーがどこで発生してる?
・エラーは発生しなかったが1件も抽出できない。
 →どのようなプログラムでどのような入力をした?
・エラーは発生せず抽出できたが、思う通りの結果でない。
 →どのようなプログラムでどのような入力をしたが、どのような思いだったがどうなってしまった?
  また、どのくらいのパターンを試した?

(ちなみに、「年月日何時何分何秒まで正確に入力しないといけない。」とのことですが、
 入力すれば出来たのでしょうか?)

前にも「躓いています。」について、ツッコミましたが、
この辺を説明していただかないと、こちらが1から検証する必要があったり、
行間を読まなきゃいけなくなり、
人によっては、それを手間と思い回答したくなくなったり、
違う意味と受け取ってしまう可能性もありますので、
最低限上記の説明をお願いします。
(5W1H等を意識すると楽にできると思います。)
(どこまでやったかを報告することにより、丸投げかどうかを判断する場合もあります。)


今回の問題についてですが、
たぶんですが、基本的にはHiDE-Adaさんの回答にある通りだと思います。
BETWEENは両値を「含む」という意味なので、
BETWEENを使用した場合と使用しない場合で、以下のようになります。
・X BETWEEN A AND B
・X >= A AND X <= B
検索したい状況等でうまく使い分ける必要があります。
また、「含みたくない」という以下のような例では使用できません。
・X > A AND X < B
・X >= A AND X < B
・X > A AND X <= B

例えば、今回の日付時刻の場合もそうですが、
「範囲指定で自至の両方を入力する場合もあるが、片方しか入力しない可能性もある」
場合等も、BETWEENを使わない方が良いケースかもしれません。
(個人的にはBETWEENはあまり使いませんが・・・)



なお、根本的な話ですが、DBは何を使っていますか?

以前の回答で、環境が提示されていないと記載しましたが、
SQL文は環境によって依存する可能性があると思います。
環境によっては意味の無い回答になっている場合になる可能性があり、
質問者さん回答者さんそれぞれに無駄が発生する可能性があります。
まずは、環境を明確にしてください。
ちなみに今自分が分かっている質問者さんの環境は
・VB2010
のみです。
何がどこまで環境に依存するかはその時々だとは思いますが、
・OS
・.NET
・DB
(それぞれ、エディション、バージョン、サービスパック有無、32ビットor64ビット等)
等、分かる範囲でかつ、伝えても問題ない範囲で極力多く情報を出すべきです。



> 今回の件でデバッグ作業の重要性を痛感しました。
> ソースコードの実力とデバッグ作業の実力の両方が無いとキツイです。

「ソースコードの実力」という表現が微妙ではありますが、
プログラミングについてはぶっちゃけ基本構文だけ押さえておけば、
それ以上はヘルプ頼りでなんとかなります。
デバッグについては全ての作業の根底になると自分は思っていますので、
しっかり身に着けた方が今後のためになると思います。
ネットが使えない状況・環境等もありますので。

本サイト(Visual Basic 中学校)の初級講座の「第41回 実行の一時停止とデバッグ」は
もうご覧になっているでしょうか?
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard41.htm
まずはじめに、これを理解できれば基礎は完璧だと思います。
他にも色々デバッグの技はありますので、それらはおいおい覚えていけば良いと思います。

投稿者 社会人  (社会人) 投稿日時 2014/2/20 15:33:47
anさん
HiDE-Adaさん

最初に謝りたい事があります。
先週投稿した際に文章が一部切れていたのを今となって分かり、要点をまとめて此方に書きます。
お手数かけますがアドバイスを宜しくお願いします。

・登録日付の検索欄はTextboxが二か所ある。
・Textboxに入力する際は年月日のみの入力制限をかける
・検索条件として年月日のみの指定、時間は指定しない。
・登録日付は範囲検索も出来る様にしたい(2014/2/1~2014/2/20の検索が出来る様にしたい。)

HiDE-Adaさん
情報有難うございます。

sql += " WHERE (登録日時 between '2014/02/01' and '2014/02/20')"

と打ち込むと登録日時が2014/02/01~2014/02/20までのデータが表示され、自分が欲しい答えに一番近いコードとなっています。
しかし、日付をTextBoxに置き換えるとビルドエラーが発生やプログラムの実行は出来るが肝心の検索結果が表示されない状況になっています。

anさん

先週のコード
sql += " WHERE (生産者番号 between " & TextBox1.Text.Trim & " and " & TextBox2.Text.Trim & ")"

だと、ビルドエラーは発生しませんが検索結果が出てきません。


======
sql += " WHERE (登録日時 between # & TextBox14.Text.Trim & # and # & TextBox15.Text.Trim & #)"
         
▼実行後にエラー▼
列名"#"が無効です。
マルチパート識別子"TextBox15.Text.Trim"をバインドできませんでした。

======
sql += " WHERE (登録日時 between " & TextBox14.Text.Trim & " and " & TextBox15.Text.Trim & ")"

エラー無し、結果は表示されない。

======
sql += " WHERE (登録日時 between '2014/02/01' and '2014/02/20')"

エラー無し、結果は表示される。イメージとしては一番近い。
======

sql += " WHERE (登録日時 between " & TextBox14.Text.Trim & " >= and <= " & TextBox15.Text.Trim & ")"

反応無し。

======

sql += " WHERE (登録日時 between " & 【>=】 TextBox14.Text.Trim & " and  " & <= TextBox15.Text.Trim & ")"
           
▼エラー▼
式が必要です

======

sql += " WHERE (登録日時 between " >= "#" & TextBox14.Text.Trim & "#" and " >= "【#" & textbox15.text.trim & "#")"】

▼エラー▼
ステートメントの終わりを指定してください。

=====

いくつかソースを確かめましたが、失敗しています。
下二つのコード【】はビルドエラーの際に発生する青い波線の変わりにしているので実際のソースには入力していません。

自分の環境はこうなっています。
▼OS▼
XP SP3 32ビット

▼VB▼
Visual Studio2010 (CDからインストールした為製品版です)

▼DB▼
SQLServer2008 R2 Manegement Studio

これで大丈夫でしょうか?
投稿者 HiDE-Ada  (社会人) 投稿日時 2014/2/20 16:09:39
僕の書いたコードをよく見てほしいのですが、
日付の前後に“'”がありますよね?

つまり、
sql += " WHERE (登録日時 between '" & TextBox1.Text.Trim & "' and '" & TextBox2.Text.Trim & "')"
となってないとダメってことです。

生産者番号が問題なかったのは数値項目だからではないでしょうか?

もうひとつ、前にも書きましたがDB上の登録日時の時刻部分が00:00:00.000でないと
後ろの部分が00:00:00.000に該当するものだけになります。
もし登録時にSYSDATEなどの関数値を設定していると、時刻部分が00:00:00.000
でないです。注意しましょう。
投稿者 an  (社会人) 投稿日時 2014/2/20 16:23:46
まずはじめに簡単なところから。

> 自分の環境はこうなっています。
> ▼OS▼
> XP SP3 32ビット

> ▼VB▼
>  Visual Studio2010 (CDからインストールした為製品版です)

> ▼DB▼
> SQLServer2008 R2 Manegement Studio

大丈夫だと思います。
できればVisual Studio2010 のエディションもあるとなお良しです。
IDEのヘルプメニュー → 一番下の方にある「バージョン情報」的なものを
クリックすれば小窓が開いて表示されると思いますが。
(こちらは2008なので少し違うかもしれませんが・・・)



> 先週投稿した際に文章が一部切れていたのを今となって分かり、要点をまとめて此方に書きます。
> お手数かけますがアドバイスを宜しくお願いします。

> ・登録日付の検索欄はTextboxが二か所ある。
> ・Textboxに入力する際は年月日のみの入力制限をかける
> ・検索条件として年月日のみの指定、時間は指定しない。
> ・登録日付は範囲検索も出来る様にしたい(2014/2/1~2014/2/20の検索が出来る様にしたい。)
> ~中略~
> ======
> sql += " WHERE (登録日時 between # & TextBox14.Text.Trim & # and # & TextBox15.Text.Trim & #)"
>           
>  ▼実行後にエラー▼
> 列名"#"が無効です。
> マルチパート識別子"TextBox15.Text.Trim"をバインドできませんでした。
> ~以下略~

要点についてはなんとなく理解しましたが、主の質問がよくわかりません。
あんまり得意ではありませんが、行間を読みます。


> ・登録日付の検索欄はTextboxが二か所ある。
→【これは自がTextBox14で、至がTextBox15】という意味。


> ・Textboxに入力する際は年月日のみの入力制限をかける
→【日付として認識できる値のみ入力できるようにする】という意味。

> ・検索条件として年月日のみの指定、時間は指定しない。
→【例えば2014/2/1~2014/2/20の入力の場合、2014/2/20 23:59:59までのレコードを抽出する】という意味。

> ・登録日付は範囲検索も出来る様にしたい(2014/2/1~2014/2/20の検索が出来る様にしたい。)
→「範囲検索【も】」というのがよくわかりませんでした。
 範囲検索ではない検索もできるようにしたいのでしょうか?
 とりあえず話が膨らみ過ぎないように、この【も】は忘れます。

> ======
> sql += " WHERE (登録日時 between # & TextBox14.Text.Trim & # and # & TextBox15.Text.Trim & #)"
> ~中略~
> ======
→【6パターンほどプログラムを作ってみたが、コンパイルエラーになるもの、実行時エラーになるもの、動作はしたが正常でないものと色々とパターンはあるが、とにかくうまくいかなかった。】という意味。

→【それらも含めて日付の範囲検索はどうすれば良いか分からないのでアドバイスがほしい】という意味。


上記に間違いがあったら指摘してください。

間違いがないという前提で、何となくアドバイスします。
(とりあえずここで一旦切って再度返信します。)


投稿者 shu  (社会人) 投稿日時 2014/2/20 16:41:28
SQLインジェクションの問題は置いておくにしても、

String.Formatを使うとかStringBuilderで文字列連結を行いAppendFormatにより連結するように
したほうがよいです。
また文字列の連結には +演算子ではなく&演算子を使うようにした方がよいです。


String.Formatの例:
> sql += " or (生産者名 Like '%" & TextBox2.Text.Trim & "%')"
sql &= String.Format(" or (生産者名 Like '%{0}%'", TextBox2.Text.Trim)


StringBuilderの例:
Imports System.Text  '<--- vbファイルの先頭に記述

Dim sql as new StringBuilder()
・・・
sql.AppendFormat(" or (生産者名 Like '%{0}%'", TextBox2.Text.Trim)


このようにした方がSQL文内の文字列がわかりやすくなります。


投稿者 an  (社会人) 投稿日時 2014/2/20 17:05:25
まずはじめに自分はほぼSQLServerは昔にちょっとしかやったことがないので、
SQLServerの詳細な挙動については
嘘があるかもしれませんので、ご了承ください。
(特に日付型などは方言があったような・・・?)




> と打ち込むと登録日時が2014/02/01~2014/02/20までのデータが表示され、自分が欲しい答えに一番近いコードとなっています。
> しかし、日付をTextBoxに置き換えるとビルドエラーが発生やプログラムの実行は出来るが肝心の検索結果が表示されない状況になっています。

TextBoxに置き換えたソースコードがないとなんとも言えませんが、話の流れから行くと、
下部6つ試したパターンの2つ目を指していますでしょうか?

とりあえず色々試したパターンでいくつかのエラーのパターンがあると思いますので、
軽く解説します。


5番目と6番目
>sql += " WHERE (登録日時 between " & 【>=】 TextBox14.Text.Trim & " and  " & <= TextBox15.Text.Trim & ")"
>            
> ▼エラー▼
> 式が必要です
>
> ======
>
> sql += " WHERE (登録日時 between " >= "#" & TextBox14.Text.Trim & "#" and " >= "【#" & textbox15.text.trim & "#")"】

> ▼エラー▼
> ステートメントの終わりを指定してください。

これについては、実行すらできないのでVBのコードに問題があります。
5番目は「&」と「>=」は連続して並ぶ事はありえないので、コンパイラが間違っている書き方だと注意しています。
6番目も似たようなものですが、よく見るとTextBox14とTextBox15で色が違ってませんでしょうか?
「"」の数が通常偶数個になるはずなのに奇数個になっているのが問題だと、コンパイラが注意しています。


1番目から4番目については、とりあえず実行できている様なので、
VBの構文としては(本当に正しいかは置いといて)許容範囲内ということです。
とりあえず、そこまで行っているのであれば、それが本当に正しいSQLかを確認してください。
どれかのパターンではSQL文に「TextBox14」とかって出ていませんか?

これは以前にも指摘しましたが、デバッグ作業です。
SQL文等のVB上ではただの文字列がDBにアクセスする際にDB側で解釈されるようなものについては、
その文字列が正しいかをMessageBoxでもなんでも良いので確認してください。
それが正しいと思ったら初めてDB側でSQL文を渡す処理を実行してください。
そうでないと、どこが間違っているかが分からないからです。

もし、正しいかよくわからないのであれば、
daive さんの 2014/2/8 20:09:21 の回答にある
SQL Server Management Studio等を使い、そのSQL文を実行してみてください。
そこでエラーが出たり、正常な結果が得られなければ、
まずは正常な結果が得られるまで、そこでSQL文を構築すべきです。

自分の場合は、まずSQL文だけを構築し、正常に動作ができることが確認できてから、
VB側にそのSQL文を組み込みます。



> sql += " WHERE (登録日時 between '2014/02/01' and '2014/02/20')"

> エラー無し、結果は表示される。イメージとしては一番近い。

近いというのはどう近いのでしょうか?
以前の話の流れを汲むと、'2014/02/20'のレコードが時分秒がオール0のものは取得できるが、
それ以外のレコードが取得できないというところが「近い」という事でしょうか?
であれば、このソースを元に進めていけば良いかと思います。

一旦テキストボックスは抜きにして、
これをどうすればほしいレコードが取れるかを考えてください。
HiDE-Adaさんの2014/2/15 17:52:46 の回答にヒントがあると思います。

そのうえで入力値(テキストボックス)と組み合わせてください。
HiDE-Adaさんの2014/2/20 16:09:39 の回答にもあるように「'」等に
注意しながら行ってください。





> anさん

> 先週のコード
> sql += " WHERE (生産者番号 between " & TextBox1.Text.Trim & " and " & TextBox2.Text.Trim & ")"

これについては、HiDE-Adaさんの回答と同じでしたので、省略します。

投稿者 名無し  (社会人) 投稿日時 2014/3/17 12:13:48

お久しぶりです。

無事に複数条件検索のプログラムが出来たので報告に参りました。

まだ、データベースプログラム自体は完成していないのでまだ質問を投稿する事も考え一旦問題解決する事にします。
再度、質問を投稿した際にはご指導宜しくお願いします。
投稿者 an  (社会人) 投稿日時 2014/3/17 15:06:25
> 無事に複数条件検索のプログラムが出来たので報告に参りました。
それは良かったですね。
差支えなければ、以下の報告をしていただければと思います。
 ・何がいけなかったか
 ・何が難しかったか
 ・何をどうしたか(最終的なプログラム等)
 ・etc
義務・ルールではありませんが、情報共有のため、
同じような人が現れた時に参考になれば良いなと思いまして。
(ちなみに個人的な感覚ではありますが、最終結果を出してくれる質問者に対しての方が回答者が回答する意欲も湧きます。)


> まだ、データベースプログラム自体は完成していないのでまだ質問を投稿する事も考え一旦問題解決する事にします。
> 再度、質問を投稿した際にはご指導宜しくお願いします。

完成までがんばってください。