質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

【VS C#】Textboxから取得したstringで検索クエリ

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,200

kamiokabegami

score 13

 前提・実現したいこと

VSのWindowsフォーム、C#にて簡単なデータベースシステムを作っています。
tblTank(Name, Nationality, Status....)というテーブルから、Nameで検索して該当するものだけ表示するクエリをTextboxを使って実装しようとしています。
クエリ自体は動いているようなのですが、結果がどんな値を入れてもNULLで返ってきてしまいます。
C言語のみ経験があり、学校の課題ということでC#でやっています。SQLやVSもあまり慣れておらず、どうすればいいのか全く見当がつきません。

 該当のソースコード

//Nameは文字列で、txtNameはTextboxに当たります。
SELECT *
FROM Tank
WHERE Name LIKE "txtName.Text"

ただし、以下のように具体的な文字や数字を指定するとしっかりと結果を返してくれます。

SELECT *
FROM Tank
WHERE Name LIKE "T34"

 試したこと

txtName.Textの前後にワイルドカードを挿入したり、一度string型に格納してから同様の処理を行うなどはしてみましたが、結果は変わらずです。

 補足情報(FW/ツールのバージョンなど)

VS 2017
DBはAccessで、VS内のデータソースから読み込んでいます。

検索をするフォーム部分のコードです

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PanzerEliteDB
{
    public partial class frmNameSearch : Form
    {
        public frmNameSearch()
        {
            InitializeComponent();
        }

        private void tankBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            this.Validate();
            this.tankBindingSource.EndEdit();
            this.tableAdapterManager.UpdateAll(this.woTDBDataSet);

        }

        private void frmNameSearch_Load(object sender, EventArgs e)
        {
            // TODO: This line of code loads data into the 'woTDBDataSet.Tank' table. You can move, or remove it, as needed.
            this.tankTableAdapter.Fill(this.woTDBDataSet.Tank);

        }

        private void button1_Click(object sender, EventArgs e)
        {

                this.tankTableAdapter.FillBy3(this.woTDBDataSet.Tank);
        }

        private void nameToolStripButton_Click(object sender, EventArgs e)
        {
            try
            {
                this.tankTableAdapter.FillBy3(this.woTDBDataSet.Tank);
            }
            catch (System.Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }

        }

        private void nameToolStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void tankBindingNavigator_RefreshItems(object sender, EventArgs e)
        {

        }
    }
}
お二方ご回答ありがとうございました。
YAmaGNZさんに教えていただいた方法で何とかクエリを完成させることができました。
パラメータ化クエリは少し勉強が必要だと今回は判断し、今後自分用のDBに勉強しながら取り組んでみます。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • YAmaGNZ

    2018/11/12 21:11

    そのSQLを構築する部分のC#のソースを提示してください。

    キャンセル

  • SurferOnWww

    2018/11/13 10:50

    補足情報を見て私の回答欄に追記しました。そちらを見てください。DB が何かの情報もよろしく。スルーは NG。フィードバックは必ず返してください。

    キャンセル

回答 2

checkベストアンサー

+5

SQLにC#側の変数を書いても、それが変数として扱われることはありません。

ソースから察するに、VisualStudioのデータソース デザイナを使用してFillBy3を作成されたのだと思います。
そのデザイナのSQLを入力するところで@Nameというような感じで@をつけるとパラメータとして扱われるようになります。
パラメータはプログラム側で変更しようとする変数のようなものだと考えてください。

SELECT *
FROM Tank
WHERE Name LIKE @Name


とすれば
例
このように@Nameと引数が表示されるはずです。
そうすれば、コードのほうで

this.tankTableAdapter.FillBy(this.woTDBDataSet.Tank,TextBox1.Text);


といった感じで引数に追加できるようになるはずです。

追記
タグを見ていませんでした。
Accessであれば、?ですね
こちらが参考になるかと思います。
また、Likeの使い方はこちらを参照してください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/15 08:08

    この際の引数の引き渡しは単純に

    this.TableAdapter.Query(this.DataSet.Table, int1, int2)

    という風にすればよいのでしょうか?
    このようにやってみたのですがうまくいきませんでした…

    キャンセル

  • 2018/11/15 09:38

    うまくいかないとはどういう状況でしょうか?
    コンパイルエラーとなるのでしょうか?
    実行したらエラーとなるのでしょうか?
    実行した結果、期待している結果にならないのでしょうか?

    「うまくいかない」は便利な言葉ですが、何をやってどうなったか説明がないと回答したくても出来ません。

    キャンセル

  • 2018/11/15 13:42

    申し訳ありません、引数の引き渡しの時に?の型と引数の型があっていなかっただけのようです。

    キャンセル

+3

C# ということですから、ADO.NET を使うのですよね? であれば、クエリをパラメータ化して、TextBox.Text の値をパラメータに代入するようにしてください。

やり方は「パラメータ化クエリ」をキーワードにググればわかると思いますが、不明な点があれば聞いてください。その際は、DB が何か(SQL Server? Access? MySQL? その他?)を書いてください。

【追記】

補足情報を見ると、Visual Studio のデーターソース構成ウィザードを使って型付 DataSet / DataTable + TableAdapter を生成して使っていて、すでに DataGridView に全レコードの一覧を表示し、それを編集して結果を DB に反映するところまではできているようですね。

さらに、それに TextBox と Button を追加して検索機能を持たせようとしているのですか?

であれば、DB に検索用のクエリを投げるのではなくて、全レコードはすでに DataSet / DataTable に取得済みなので、それをフィルタリングして DataGridView に表示した方がよさそうです。

詳しい方法が不明でしたら聞いてください。DB が何かの情報もよろしく。

【追記2】

上の追記で、

DB に検索用のクエリを投げるのではなくて、全レコードはすでに DataSet / DataTable に取得済みなので、それをフィルタリングして DataGridView に表示した方がよさそうです。

と書きましたが、そのコード例を書いておきます。

使った DB は SQL Server の Northwind サンプルデータベースの Products テーブルです。button1_Click メソッドで DataTable.DefaultView.RowFilter を使ってフィルタリングしているところに注目してください。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }

        private void productsBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            this.Validate();
            this.productsBindingSource.EndEdit();
            this.tableAdapterManager.UpdateAll(this.northwindDataSet);
        }

        private void Form3_Load(object sender, EventArgs e)
        {
            this.productsTableAdapter.Fill(this.northwindDataSet.Products);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(this.textBox1.Text))
            {
                NorthwindDataSet.ProductsDataTable table = this.northwindDataSet.Products;
                table.DefaultView.RowFilter = "ProductName LIKE '%" + this.textBox1.Text + "%'";
                this.productsBindingSource.DataSource = this.northwindDataSet.Products;
            }
            else
            {
                NorthwindDataSet.ProductsDataTable table = this.northwindDataSet.Products;
                table.DefaultView.RowFilter = "";
            }
        }
    }
}

TextBox に "cha" と入力して Search ボタンをクリックし、ProductName LIKE '%cha%' で検索した結果が下の画像です。

イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/13 16:54

    反応が遅くなり申し訳ありません
    パラメータ化クエリなるものを自分でも調べてみたのですが、よくわからず、少し立ち戻ったところから見直し始めたところです。

    のちに補足にも追記しますが、DBはAccessです。


    どの方法で自分が理解できるか少し試してみます…

    キャンセル

  • 2018/11/13 17:13

    少し話がずれますが、このelse分岐では、TextBoxがNullであった場合、"(空白)"に合致する部分、すなわちテーブル全体を表示するという解釈であっていますか?

    キャンセル

  • 2018/11/13 17:56

    合ってます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る