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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

5646閲覧

[C#]SQLParameterの変数(@xx)をインクリメントしたい

superhiro

総合スコア7

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2020/01/22 01:04

前提・実現したいこと

SQLサーバとC#にて自社金属加工業で使うソフトの開発を行っています。
素人が作った切り貼りだらけの読みにくいコードで申し訳ありません。

問題となっている処理の流れは以下のとおりです。
1.条件に合致する社名を抽出し、リストへ詰め込む
2.1に合致する件数分3の処理をループさせる
3.1で抽出した社名を条件に合致する品目を抽出しリストへ詰め込む(ここで問題発生)
4.リストの内容を元に後処理を実行(未実装)

発生している問題・エラーメッセージ

System.Data.SqlClient.SqlException: '変数名 '@results' は既に宣言されています。変数名は、クエリ バッチまたはストアド プロシージャ内で一意にしてください。'

該当のソースコード

C#

1 private void button4_Click(object sender, EventArgs e) 2 { 3 String nyuryokudate = dateTimePicker2.Text; 4 5 { 6 var results = new List<string>(); 7 string constr = @"接続…"; 8 using (var connection = new SqlConnection(constr)) 9 using (var command = connection.CreateCommand()) 10 11 try 12 { 13 connection.Open(); 14 command.CommandText = "select 会社 from zairyoTBL where 入力日 = @nyuryokudate and フラグ is null group by 会社"; 15 command.Parameters.Add(new SqlParameter("@nyuryokudate", nyuryokudate)); 16 SqlDataReader sdr = command.ExecuteReader(); 17 while (sdr.Read() == true) 18 { 19 results.Add(sdr["会社"].ToString()); 20 } 21 sdr.Close(); 22 } 23 catch (Exception exception) 24 { 25 Console.WriteLine(exception.Message); 26 return; 27 } 28 finally 29 { 30 //コネクションクローズ 31 connection.Close(); 32 } 33 int count = results.Count(); 34 35 var results2 = new List<string>(); 36 string constr2 = @"接続…"; 37 using (var connection2 = new SqlConnection(constr2)) 38 using (var command2 = connection2.CreateCommand()) 39 40 try 41 { 42 //コネクションオープン 43 connection2.Open(); 44 //SQL生成 45 command2.Parameters.Add(new SqlParameter("@nyuryokudate2", nyuryokudate)); 46 47 for (int i=0;i<=count;++i) 48 { 49 command2.Parameters.Add(new SqlParameter("@results", results[i]));//ここの@resultsがループの際、重複しているエラーが出ている。 50 command2.CommandText = "select 材質1,径1,長さ1,数量1,単価1,硬度1,その他1,数量2,単価2,会社 from zairyoTBL where 入力日=@nyuryokudate2 and 会社=@results and フラグ is null"; 51 SqlDataReader sdr2 = command2.ExecuteReader(); 52 while (sdr2.Read() == true) 53 { 54 results2.Add(sdr2["材質1"].ToString()); 55 results2.Add(sdr2["径1"].ToString()); 56 results2.Add(sdr2["長さ1"].ToString()); 57 results2.Add(sdr2["数量1"].ToString()); 58 results2.Add(sdr2["単価1"].ToString()); 59 results2.Add(sdr2["硬度1"].ToString()); 60 results2.Add(sdr2["その他1"].ToString()); 61 results2.Add(sdr2["数量2"].ToString()); 62 results2.Add(sdr2["単価2"].ToString()); 63 results2.Add(sdr2["会社"].ToString()); 64 } 65 Console.WriteLine("[{0}]", string.Join(", ", results2)); 66 sdr2.Close(); 67 68 } 69 } 70 catch (Exception exception) 71 { 72 Console.WriteLine(exception.Message); 73 return; 74 } 75 finally 76 { 77 //コネクションクローズ 78 connection2.Close(); 79 }

試したこと

ループの際のSqlParameterの変数をインクリメントできれば良いと思い
SqlParameter("@results"+[i],results[i])
としてみたりしたのですが、文法が違うようでうまくいきませんでした。

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

ここにより詳細な情報を記載してください。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

発生している問題、

System.Data.SqlClient.SqlException: '変数名 '@results' は既に宣言されています。

に対する直接の解決策のレスではなくて(それはすでに回答されているようですので)、こうした方がよさそうという提案ですが・・・

1.条件に合致する社名を抽出し、リストへ詰め込む
2.1に合致する件数分3の処理をループさせる
3.1で抽出した社名を条件に合致する品目を抽出しリストへ詰め込む(ここで問題発生)

上の 1 の条件というのは zairyoTBL テーブルの「入力日」と「フラグ」ですよね。

ということは、要するに、zairyoTBL テーブルから「入力日」と「フラグ」が特定の条件(where 入力日 = @nyuryokudate and フラグ is null)でレコードを抽出し、抽出したレコードを「会社」ごとに並べてリスト(List<string> 型のオブジェクト)に詰め込みたいのですよね?

そうであれば、上の 1 ~ 3 のステップを踏む必要はなくて、SELECT クエリを以下のようにして一発で希望のレコードは抽出できるのではないですか?

select 材質1,径1, ... ,会社 from zairyoTBL where 入力日=@nyuryokudate2 and フラグ is null order by 会社

私の思い違いがあれば指摘ください。

投稿2020/01/22 04:20

編集2020/01/22 04:51
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

superhiro

2020/01/22 05:58

>抽出したレコードを「会社」ごとに並べてリスト(List<string> 型のオブジェクト)に詰め込みたいのですよね? はい。Listに詰め込む目的としては、次の処理で会社ごとの明細をSQLで抽出し、加工して会社ごとに注文書みたいな形で出力したいために、条件となる社名が必要かと思い一次処理として行いました。 もっと良いやり方があるのかもしれませんが、持っている知識でできるやり方で作ってみました。
退会済みユーザー

退会済みユーザー

2020/01/22 06:07 編集

> 持っている知識でできるやり方で作ってみました。 私が提案したやり方は、上のレスの「要するに」というところの理解が正しければという条件付きですが、今質問に書かれているよりはるかに簡単に、もちろん持っている知識で、必要なレコードを抽出できると思うのですが。何か条件に合わないのですかね?
superhiro

2020/01/22 06:18

私が難しく考えているだけかもしれませんが、会社ごとのデータに後処理で成形する際、SQL結果がその会社分のデータになっていないとだめなんじゃないかと思っているためです。提案頂いた内容ですと、会社ごとに並びますが、複数の会社分のデータが帰ってきてしまいます。すると、後処理でまた会社ごとに分割しないといけないのではないでしょうか。
退会済みユーザー

退会済みユーザー

2020/01/22 06:32

上のレスの「会社ごとに注文書」の例で言うと、実際は質問のコードの for ループの中の最後に注文書を作成するコードがあって、ループが一回回るたびに(即ち会社ごとに)注文書を作りたいということだったようですね。そこが読めてなかったです。すみません。
superhiro

2020/01/22 06:40

はい、そのようにしたいと思っています。 だた、今調べていたらListの中身をフィルタして抽出できるようですので、ご提示頂いた方法でList化して、条件を与えて会社ごとに抽出もできそうです。 ありがとうございました。
guest

0

ベストアンサー

command2.Parameters.Add(new SqlParameter("@results", results[i]));
これは「@results」という名前のパラメータを新しく作成しcommand2のパラメータに追加するということです。
ですので、すでに前のループで「@results」という名前のパラメータは追加されているので「同じ名前のパラメータは追加できません」とエラーとなります。

ではどうやってパラメータの値を変更するかですが

C#

1command.Parameters["@results"].Value = i;

というような形で値を代入できます。

これはおせっかいですが、
「インクリメント」とは一般的に+1していくことを指す言葉で、値を変更するという意味ではないです。
インクリメント(ウィキペディア)

投稿2020/01/22 01:18

編集2020/01/22 01:23
YAmaGNZ

総合スコア10222

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

superhiro

2020/01/22 04:07

プログラミングを始めたばかりで用語もままならず、伝わりづらい表現もあったかと思いますが、ご回答頂きありがとうございます。 ループ1周目のSQLを ```C# command2.CommandText = "select 材質1,径1,長さ1,数量1,単価1,硬度1,その他1,数量2,単価2,会社 from zairyoTBL where 入力日=@nyuryokudate2 and 会社='results[0]' and フラグ is null"; ``` 2周目のSQLを ```C# command2.CommandText = "select 材質1,径1,長さ1,数量1,単価1,硬度1,その他1,数量2,単価2,会社 from zairyoTBL where 入力日=@nyuryokudate2 and 会社='results[1]' and フラグ is null"; ``` のようにしたいと思い、@resultsの名前に連番をつけて重複しないようにし、それに対してresults[0]やresults[1]を代入すれば良いかなぁと思っていました。 そのため、連番の意味でインクリメントと表現していました。 さて、回答いただいた内容ですが、 ```C# command.Parameters["@results"].Value = i; ``` これは、@resultsのパラメータをiにする。という意味でしょうか? ```C# command2.Parameters.Add(new SqlParameter("@results", results[i])); command2.Parameters["@results"].Value = i; command2.CommandText = "select 材質1,径1,長さ1,数量1,単価1,硬度1,その他1,数量2,単価2,会社 from zairyoTBL where 入力日=@nyuryokudate2 and 会社=@results and フラグ is null"; ``` これで、上述のような処理になるのかがあまり理解できていません。 処理は先に進みましたが、別のエラーが出て対応しているところです。
YAmaGNZ

2020/01/22 04:18

まず、新しいパラメータを追加するのはループの外にしなければ、2重定義となってしまいます。 これについては対応されましたでしょうか? また、私の回答はそのままコピペしても意味がありません。 あくまで@resultsというパラメータの値をiにするという例です。 実際にどのような値にするかはご自身で決定してください。 また、Valueプロパティについては SqlParameter.Value プロパティ(https://docs.microsoft.com/ja-jp/dotnet/api/system.data.sqlclient.sqlparameter.value?view=netframework-4.8)をご覧ください。
superhiro

2020/01/22 05:13

Addをループの外に出して、パラメーター値の変更内容をresults[i]にすることで思っていた処理にすることができました。ただ、予想していた出力結果になっていなかったので、その他改修したいと思います。 貴重なお時間ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問