none
INSERTに「演算子がありません」構文エラーが発生 RRS feed

  • 質問

  • 初めて質問します。プログラミング初心者で勉強中の身です。
    タイトル通りのエラーが出て困っています。自分なりに色々と調べて、値を直接入力してみたりしたのですが、エラーがでます。
    また、スペースが入っていないという原因でもないみたいです。

    行き詰まりました・・。ご教授の程、お願いします。
    <環境>
    visual studio 2005 c# mdb

    <ソース>
           private void ImportButton_Click(object sender, EventArgs e)
    {
    OleDbConnection connect = new OleDbConnection(this.shohin_TableTableAdapter.Connection.ConnectionString);
          connect.Open();
    OleDbTransaction transaction = null;
    transaction = connect.BeginTransaction();
    OleDbCommand komando = new OleDbCommand();
    komando.Connection = connect;
    komando.Transaction = transaction;
    DataSet CSVDataSet = new DataSet();
    DataTable CSVTable = new DataTable();
    CSVDataSet.Tables.Add("CSVTable");
    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinCd", Type.GetType("System.String"));
    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinName", Type.GetType("System.String"));
    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinDate", Type.GetType("System.String"));
    try
    {
    //テーブルのレコードを全削除
      this.shohin_TableTableAdapter.DeleteLine();
    //CSVを読み込む為のStreamReaderクラスを作成
         StreamReader reader = new StreamReader(OpenTextBox.Text, Encoding.GetEncoding("Shift_JIS"));
       //Peekメソッド・・次に読み込む文字があるかないかを確認する
    while (reader.Peek() != -1)
    {
    String[] CSVData;
    CSVData = reader.ReadLine().Split(',');
    //DataSetの作成
    DataRow CSVRow;
    CSVRow = CSVDataSet.Tables["CSVTable"].NewRow();
    for (int counter = 0; counter < CSVData.Length; counter++)
    {
    CSVRow[counter] = CSVData[counter];
      }
    CSVDataSet.Tables["CSVTable"].Rows.Add(CSVRow);
    foreach (DataRow CSV in CSVDataSet.Tables["CSVTable"].Rows) ;
    Console.WriteLine((CSVRow[0]).ToString() + "," + (CSVRow[1]).ToString() + "," + (CSVRow[2]).ToString());
    if (CSVRow[0].ToString().Equals("ShohinCd"))
      { }
    else
      {
    //CSVファイルのレコードをインサート
    int SCd = int.Parse(CSVRow[0].ToString());
    string SName = CSVRow[1].ToString();
    DateTime SDate = DateTime.Parse(CSVRow[2].ToString());
    komando.CommandText = "INSERT INTO `Shohin_Table` ( `ShohinCd`, `ShohinName`, `ShohinDate` ) VALUES (" + SCd + " , " + SName + " , " + SDate + " )";
    komando.ExecuteNonQuery();
    }
    }
    OpenTextBox.Clear();
    2009年4月24日 7:02

回答

  • すいません。自己解決しました。
    数々のアドバイスありがとうございました。

    完成したソースは下記のようになり、OleDbParameterCollectionにパラメータ@ShohinCdが作られていなかったこと、
    一行ずつ読み込んでいるので、一行ずつSQLを実行する必要があり(←これは自信ありません)、while文の中に
    komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( ?, ?, ? )";
    komando.ExecuteNonQuery();
    が必要でした。

    完成ソース
           private void ImportButton_Click(object sender, EventArgs e)
            {
                
                OleDbConnection connect = new OleDbConnection(this.shohin_TableTableAdapter.Connection.ConnectionString);
                connect.Open();
                
                OleDbTransaction transaction = null;
    
                transaction = connect.BeginTransaction();
    
                OleDbCommand komando = new OleDbCommand();
    
                komando.Connection = connect;
    
                komando.Transaction = transaction;
    
                    DataSet CSVDataSet = new DataSet();
                    DataTable CSVTable = new DataTable();
    
                    CSVDataSet.Tables.Add("CSVTable");
    
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinCd", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinName", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinDate", Type.GetType("System.String"));
    
                    try
                    {
    
                            //テーブルのレコードを全削除
                            //this.shohin_TableTableAdapter.DeleteLine();   一時コメント
    
                            //CSVを読み込む為のStreamReaderクラスを作成
                            StreamReader reader = new StreamReader(OpenTextBox.Text, Encoding.GetEncoding("Shift_JIS"));
    
                            //Peekメソッド・・次に読み込む文字があるかないかを確認する
                            //        なければー1を返す
                            while (reader.Peek() != -1)
                            {
                                String[] CSVData;
                                CSVData = reader.ReadLine().Split(',');
    
                                //DataSetの作成
                                DataRow CSVRow;
    
                                CSVRow = CSVDataSet.Tables["CSVTable"].NewRow();
                                for (int counter = 0; counter < CSVData.Length; counter++)
                                {
                                    CSVRow[counter] = CSVData[counter];
                                }
    
                                CSVDataSet.Tables["CSVTable"].Rows.Add(CSVRow);
    
    
                                foreach (DataRow CSV in CSVDataSet.Tables["CSVTable"].Rows) ;
                                Console.WriteLine((CSVRow[0]).ToString() + "," + (CSVRow[1]).ToString() + "," + (CSVRow[2]).ToString());
    
    
                                if (CSVRow[0].ToString().Equals("ShohinCd"))
                                { }
                                else
                                {
    
    
                                    //CSVファイルのレコードをインサート
                                  
                                    int SCd = int.Parse(CSVRow[0].ToString());
                                    string SName = CSVRow[1].ToString();
                                    DateTime SDate = DateTime.Parse(CSVRow[2].ToString());
    
    
                                  
                                    komando.Parameters.Add("@ShohinCd", OleDbType.Variant);
                                    komando.Parameters.Add("@ShohinName", OleDbType.VarChar);
                                    komando.Parameters.Add("@ShohinDate", OleDbType.Date);
                                    
                                    komando.Parameters["@ShohinCd"].Value = SCd;
                                    komando.Parameters["@ShohinName"].Value = SName;
                                    komando.Parameters["@ShohinDate"].Value = SDate;
                                    
                                    
    
                                }
    
                                komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( @ShohinCd, @ShohinName, @ShohinDate )";
    
                                komando.ExecuteNonQuery();
    
                               
                            }
    
    
    インサート文の中の?も@ShohinCdと変更しました。

    これがどこまで正しいのか、要領よく実行できているのか私にはまだまだ全然判断出来ませんが、とりあえず動くようになり、一歩前進です。
    助言を頂いた方々、ありがとうございました。 
    2009年4月30日 6:09
  • 返信ありがとうございます。

    すいません、今返信に気づきました。

    そして完成コードとして記載したものが間違ってました。ごめんなさい。

    現在は以下のようになってます。
            private void ImportButton_Click(object sender, EventArgs e)
            {
                
                OleDbConnection connect = new OleDbConnection(this.shohin_TableTableAdapter.Connection.ConnectionString);
                connect.Open();
    
                    DataSet CSVDataSet = new DataSet();
                    DataTable CSVTable = new DataTable();
    
                    CSVDataSet.Tables.Add("CSVTable");
    
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinCd", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinName", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinDate", Type.GetType("System.String"));
    
                    OleDbTransaction transaction = null;
    
                    OleDbCommand komando = new OleDbCommand();
    
                    komando.Connection = connect;
                    //トランザクションの開始
                    transaction = connect.BeginTransaction();
                    komando.Transaction = transaction;
    
                    try
                    {
                       //テーブルのレコードを全削除
                        komando.CommandText = "DELETE FROM Shohin_Table";
                        //CSVを読み込む為のStreamReaderクラスを作成
                        StreamReader reader = new StreamReader(OpenTextBox.Text, Encoding.GetEncoding("Shift_JIS"));
    
                        //Peekメソッド・・次に読み込む文字があるかないかを確認する
                        //        なければー1を返す
                        while (reader.Peek() != -1)
                        {
                            String[] CSVData;
                            CSVData = reader.ReadLine().Split(',');
    
                            //DataSetの作成
                            DataRow CSVRow;
    
                            CSVRow = CSVDataSet.Tables["CSVTable"].NewRow();
                            for (int counter = 0; counter < CSVData.Length; counter++)
                            {
                                CSVRow[counter] = CSVData[counter];
                            }
    
                            CSVDataSet.Tables["CSVTable"].Rows.Add(CSVRow);
    
                            foreach (DataRow CSV in CSVDataSet.Tables["CSVTable"].Rows) ;
                            Console.WriteLine((CSVRow[0]).ToString() + "," + (CSVRow[1]).ToString() + "," + (CSVRow[2]).ToString());
    
                            if (CSVRow[0].ToString().Equals("ShohinCd"))
                            { }
                            else
                            {
                                int SCd = int.Parse(CSVRow[0].ToString());
                                string SName = CSVRow[1].ToString();
                                DateTime SDate = DateTime.Parse(CSVRow[2].ToString());
    
                                //パラメータを作成
                                komando.Parameters.Add("@ShohinCd", OleDbType.Variant);
                                komando.Parameters.Add("@ShohinName", OleDbType.VarChar);
                                komando.Parameters.Add("@ShohinDate", OleDbType.Date);
    
                                //パラメータに値を代入
                                komando.Parameters["@ShohinCd"].Value = SCd;
                                komando.Parameters["@ShohinName"].Value = SName;
                                komando.Parameters["@ShohinDate"].Value = SDate;
    
                                komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( @ShohinCd, @ShohinName, @ShohinDate )";
                                //SQLを実行
                                komando.ExecuteNonQuery();
                                
                            }
    
                        }
                            OpenTextBox.Clear();
                            reader.Close();
    
                        }
    
                        catch (System.Exception)
                        {
                            if (transaction != null)
                            {
                                transaction.Rollback();
                                //komando.Transaction.Rollback();
                                transaction.Dispose();
                                transaction = null;
                            }
                            System.Windows.Forms.MessageBox.Show("エラーだよ");
                        }
                        finally
                        {
                            // 正常の場合はコミット
                            if (transaction != null)
                            {
                                //コミット
                                komando.Transaction.Commit();
    
                                //コミットした結果をグリッドに表示させる
                                this.shohin_TableTableAdapter.Fill(dataBaseDataSet.Shohin_Table);
    
                                MessageBox.Show("CSVファイルを取り込みました。");
    
                                transaction.Dispose();
                                transaction = null;
                            }
                        }
            }
    2009年5月1日 8:15

すべての返信

  • どの行でエラーが出ているのでしょうか? 試していませんが、ぱっと見たところ、「`」が影響しているように思えます。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年4月24日 8:10
    モデレータ
  • ごめんなさい、情報不足ですよね。
    エラーは
    komando.ExecuteNonQuery();
    でSQLを実行した際に、
    クエリ式 '2009/08/09 0:00:00' の 構文エラー : 演算子がありません。
    というエラーが発生します。これはShohinDateの日付になってます。

    「'」を外してみましたが、結果は同じでした。
    2009年4月24日 8:17
  • mdbだと日付を#で囲む必要があったんじゃないかと思います。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年4月24日 8:19
    モデレータ
  • 返信ありがとうおございます。
    trapemiyaさんの助言通り、

    komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES (" + SCd + " , " + SName + " , #" + SDate + "# )";
                                          komando.ExecuteNonQuery();

    としてみましたが、エラーが変わり下記のようにでるようになりました。

    「1 つ以上の必要なパラメータの値が設定されていません。」
    2009年4月24日 8:32
  • いえ、'#2009/08/09 0:00:00#' な感じになるようにしてみて下さい。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年4月24日 8:35
    モデレータ
  • 要領悪くてすみません・・。
    下記の用に記述してみましたが、

    komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES (" + SCd + " , " + SName + " , " + #SDate# + " )";

    「プリプロセッサ ディレクティブは行でスペース以外の最初の文字でなければなりません。」

    というエラーがでて実行が出来ませんでした。

    最初で出したエラーは構文エラーということなので、SQL文の書き方が間違っているという認識でいるのはよろしいでしょうか?
    2009年4月24日 8:45
  • SQL で使うパラメータには OleDbCommand.Parameters を使用することをお勧めします。
    command.CommandText は(略) VALUES (?, ?, ?) としておき、
    command.Parameters.AddWithValue("@ShohinCd", SCd);
    command.Parameters.AddWithValue("@ShohinName", SName);
    command.Parameters.AddWithValue("@ShohinDate", SDate);
    みたいに(OleDb の場合 AddWithValue の第一引数は実際には使用されず、Parameters に追加する順番でどの ? に値を挿入するかが決まります)。

    2009年4月24日 9:03
  • 返信ありがとうございます。
    パラメータを使うこちらのやり方の方が確実でスッキリしてみえますね。
    今回勉強用に使っているSQLはフィールドが少ないのでその差はでませんが、
    業務で大量のレコードを使う際にはこちらの方がきっといいんですね。
    貴重なアドバイスをありがとうございます。

    Hongliangさんの助言どおり、下記のソースで試してみました。
    komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( ?, ?, ? )";
                                    komando.Parameters.AddWithValue("@ShohinCd", SCd);
                                    komando.Parameters.AddWithValue("@ShohinName", SName);
                                    komando.Parameters.AddWithValue("@ShohinDate", SDate);
                                   
    で、一つ目のレコードは通ったのですが、二つ目のレコードにいったときに例外でスローされてしまいました。
    エラーの内容は
    「インデックス、主キー、またはリレーションシップで値が重複しているので、テーブルを変更できませんでした。重複する値のあるフィールドの値を変更するか、インデックスを削除してください。または重複する値を使用できるように再定義してください。」
    なんですが、レコードは試すたびに新しいのを作っていて、重複している箇所もありません。

    もう頭が???でいっぱいです。
    2009年4月24日 9:23
  • > 一つ目のレコードは通ったのですが、二つ目のレコードにいったときに例外でスローされてしまいました。

    ということから、どこかのフィールドが「重複なし」の設定になっていて、2つ目のレコードでそのフィールドが
    重複しているというのが一番可能性が高そうです。

    > レコードは試すたびに新しいのを作っていて、重複している箇所もありません。

    とのことですけど、落ち着いてもう一度よ~くチェックしてみてはいかがですか。

    2009年4月24日 13:42
  • komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES (" + SCd + " , " + SName + " , " + #SDate# + " )";

    「プリプロセッサ ディレクティブは行でスペース以外の最初の文字でなければなりません。」

    というエラーがでて実行が出来ませんでした。

    komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES (" + SCd + " , " + SName + " , '#" + SDate + "#' )";

    のような感じです。しかし、Hongliangさんが言われているように、このようにSQL文を組み立ててはいけません。SQLインジェクションの原因になります。既にされているようにパラメータライズドクエリを用いるのが正解です。

    「インデックス、主キー、またはリレーションシップで値が重複しているので、テーブルを変更できませんでした。重複する値のあるフィールドの値を変更するか、インデックスを削除してください。または重複する値を使用できるように再定義してください。」なんですが、レコードは試すたびに新しいのを作っていて、重複している箇所もありません。
    まずShohin_Tableの定義を見て、主キーなど重複してはいけない列を確認して下さい。その上で最初のレコードで挿入するSCd, SName, SDateと次のレコードで挿入するそれらが重複していないかを確認して下さい。
    確認の仕方はわかりますか?ブレークポイントやトレースポイント挿入し、デバッグ実行します。
    そこで確認した結果、重複がなければ、OLEDBにおける型変換によって結果的に同じ値をmdbに挿入しようとしているのかもしれません。CSVから挿入しようとされていますので、1行目のみ残したCSVを読み込ませてmdbを確認し、同様に2行目のみ残したCSVを読み込ませてmdbを確認し、両者を比較してみるとヒントが得られるかもしれません。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年4月24日 14:23
    モデレータ
  • 返信そして親切なアドバイスをありがとうございます。

    本日から2,3日ほど他のプロジェクトのテストに入るで試せないのですが、
    テスト終了後にさっそくやってみたいと思います。

    皆様、ほんとにありがとうございます。
    2009年4月27日 1:45
  • お世話になってます。
    1行のみのCSVはやはりインサートできました。
    次に、2行のCSVファイルを(データは最初の全く違うデータ)インサートしてみましたが、
    やはり落ちました・・。
    komando.ExecuteNonQuery();
    で落ちているのだと思いますが、データが違うのに
    「インデックス、主キー、またはリレーションシップで値が重複しているので、テーブルを変更できませんでした。重複する値のあるフィールドの値を変更するか、インデックスを削除してください。または重複する値を使用できるように再定義してください。」
    とでるので、未だ解決できずにいます。

    最新のソースは下記の通りとなってます。
     private void ImportButton_Click(object sender, EventArgs e)
            {
                
                OleDbConnection connect = new OleDbConnection(this.shohin_TableTableAdapter.Connection.ConnectionString);
                connect.Open();
                OleDbTransaction transaction = null;
    
                transaction = connect.BeginTransaction();
    
                OleDbCommand komando = new OleDbCommand();
    
                komando.Connection = connect;
    
                komando.Transaction = transaction;
    
                    DataSet CSVDataSet = new DataSet();
                    DataTable CSVTable = new DataTable();
    
                    CSVDataSet.Tables.Add("CSVTable");
    
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinCd", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinName", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinDate", Type.GetType("System.String"));
    
                   
    
                    try
                    {
    
                            //CSVを読み込む為のStreamReaderクラスを作成
                            StreamReader reader = new StreamReader(OpenTextBox.Text, Encoding.GetEncoding("Shift_JIS"));
    
                            //Peekメソッド・・次に読み込む文字があるかないかを確認する
                            //        なければー1を返す
                            while (reader.Peek() != -1)
                            {
                                String[] CSVData;
                                CSVData = reader.ReadLine().Split(',');
    
                                //DataSetの作成
                                DataRow CSVRow;
    
                                CSVRow = CSVDataSet.Tables["CSVTable"].NewRow();
                                for (int counter = 0; counter < CSVData.Length; counter++)
                                {
                                    CSVRow[counter] = CSVData[counter];
                                }
    
                                CSVDataSet.Tables["CSVTable"].Rows.Add(CSVRow);
    
    
                                foreach (DataRow CSV in CSVDataSet.Tables["CSVTable"].Rows) ;
                                Console.WriteLine((CSVRow[0]).ToString() + "," + (CSVRow[1]).ToString() + "," + (CSVRow[2]).ToString());
    
    
                                if (CSVRow[0].ToString().Equals("ShohinCd"))
                                { }
                                else
                                {
    
    
                                    //CSVファイルのレコードをインサート
                                  CSVRow[1].ToString(), DateTime.Parse(CSVRow[2].ToString()));
                                    int SCd = int.Parse(CSVRow[0].ToString());
                                    string SName = CSVRow[1].ToString();
                                    DateTime SDate = DateTime.Parse(CSVRow[2].ToString());
                                    komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( ?, ?, ? )";
                                    komando.Parameters.AddWithValue("@ShohinCd", SCd);
                                    komando.Parameters.AddWithValue("@ShohinName", SName);
                                    komando.Parameters.AddWithValue("@ShohinDate", SDate);
                                    
                                    komando.ExecuteNonQuery();
                                    
                                }
    
                            }
                            OpenTextBox.Clear();
    
                        this.shohin_TableTableAdapter.Fill(dataBaseDataSet.Shohin_Table);
    
                        MessageBox.Show("CSVファイルを取り込みました。");
    while文がおかしいのでしょうか・・  う~ん・・・・・。
    2009年4月29日 23:53
  • komando の宣言が while の外側なのに対して、AddWithValue がループの中にあるのが原因ではないでしょうか。

    1レコード目の実行時には AddWithValue でパラメータの 1~3 を追加&値設定していますが、2レコード目の実行時にはパラメータの 4~6 を追加&設定しているように思います。ここでパラメータの 1~3 には変化がなく、INSERT 実行時に使用されるパラメータは 1~3 番目なので、1レコード目と同じ値で INSERT してしまうように思います。

    while の外で

     komando.Parameters.Add("@ShohinCd", OleDbType.VarChar);

    といったパラメータの追加だけをしておいて、while の中で

     komando.Parameters("@ShohinCd").Value = SCd;

    などと値を設定だけしてあげればいいと思います。

    komando.CommandText の設定も while の外で 1回やればいいように思えますね。
    2009年4月30日 0:24
  • 回答ありがとうございます。

    すいません・・なんとか自分で解決しようと、頂いたアドバイスで色々とやってみたんですが、エラーがでてまたハマっています・・。

    ソースは whileの中を

    komando.Parameters["@SHohinCd"].Value = SCd;
    komando.Parameters["@SHohinName"].Value = SName;
    komando.Parameters["@SHohinDate"].Value = SDate;
    としました。 ()ではなく []でした。

    whileの外は
    komando.Parameters.Add("@ShohinCd", OleDbType.Variant);
    komando.Parameters.Add("@ShohinName", OleDbType.VarChar);
    komando.Parameters.Add("@ShohinDate", OleDbType.Date);
    
    komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( ?, ?, ? )";
    
    komando.ExecuteNonQuery();
                            
    としました。

    実行してエラーがでるのは
    komando.Parameters["@SHohinCd"].Value = SCd;
    の部分で、"OleDbParameter は、この OleDbParameterCollection に含まれていません"というエラーが発生します。
    この意味も調べたのですが、よくわからず再度ここに至りました。
    名前空間が足りないとかじゃないですよね。それだとコンパイル時にエラーとなるのですよね。

    すいません、再度おねがいいたします。
    2009年4月30日 2:35
  • OleDbParameterCollectionとはOleDbParameter の集まりであり、その集まりの中に@SHohinCdという名前のパラメータは無いよと言われています。ブレークポイントで止めてOleDbParameterCollectionの中身を調べてみられると良いでしょう。
    ご提示されたコードでは、パラメータ追加時が@ShohinCdで、Value設定時が@SHohinCdとなっています。はっきり覚えていませんが、大文字小文字の違いを認識するのかもしれません。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年4月30日 5:24
    モデレータ
  • 返信ありがとうございます。

    大文字小文字を直しましたが、結果かわりませんでした。

    いまのエラーはやはり
      "ParameterName '@ShohinCd' を持つ OleDbParameter は、この OleDbParameterCollection に含まれていません。"

    となりました。
    2009年4月30日 5:38
  • すいません。自己解決しました。
    数々のアドバイスありがとうございました。

    完成したソースは下記のようになり、OleDbParameterCollectionにパラメータ@ShohinCdが作られていなかったこと、
    一行ずつ読み込んでいるので、一行ずつSQLを実行する必要があり(←これは自信ありません)、while文の中に
    komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( ?, ?, ? )";
    komando.ExecuteNonQuery();
    が必要でした。

    完成ソース
           private void ImportButton_Click(object sender, EventArgs e)
            {
                
                OleDbConnection connect = new OleDbConnection(this.shohin_TableTableAdapter.Connection.ConnectionString);
                connect.Open();
                
                OleDbTransaction transaction = null;
    
                transaction = connect.BeginTransaction();
    
                OleDbCommand komando = new OleDbCommand();
    
                komando.Connection = connect;
    
                komando.Transaction = transaction;
    
                    DataSet CSVDataSet = new DataSet();
                    DataTable CSVTable = new DataTable();
    
                    CSVDataSet.Tables.Add("CSVTable");
    
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinCd", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinName", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinDate", Type.GetType("System.String"));
    
                    try
                    {
    
                            //テーブルのレコードを全削除
                            //this.shohin_TableTableAdapter.DeleteLine();   一時コメント
    
                            //CSVを読み込む為のStreamReaderクラスを作成
                            StreamReader reader = new StreamReader(OpenTextBox.Text, Encoding.GetEncoding("Shift_JIS"));
    
                            //Peekメソッド・・次に読み込む文字があるかないかを確認する
                            //        なければー1を返す
                            while (reader.Peek() != -1)
                            {
                                String[] CSVData;
                                CSVData = reader.ReadLine().Split(',');
    
                                //DataSetの作成
                                DataRow CSVRow;
    
                                CSVRow = CSVDataSet.Tables["CSVTable"].NewRow();
                                for (int counter = 0; counter < CSVData.Length; counter++)
                                {
                                    CSVRow[counter] = CSVData[counter];
                                }
    
                                CSVDataSet.Tables["CSVTable"].Rows.Add(CSVRow);
    
    
                                foreach (DataRow CSV in CSVDataSet.Tables["CSVTable"].Rows) ;
                                Console.WriteLine((CSVRow[0]).ToString() + "," + (CSVRow[1]).ToString() + "," + (CSVRow[2]).ToString());
    
    
                                if (CSVRow[0].ToString().Equals("ShohinCd"))
                                { }
                                else
                                {
    
    
                                    //CSVファイルのレコードをインサート
                                  
                                    int SCd = int.Parse(CSVRow[0].ToString());
                                    string SName = CSVRow[1].ToString();
                                    DateTime SDate = DateTime.Parse(CSVRow[2].ToString());
    
    
                                  
                                    komando.Parameters.Add("@ShohinCd", OleDbType.Variant);
                                    komando.Parameters.Add("@ShohinName", OleDbType.VarChar);
                                    komando.Parameters.Add("@ShohinDate", OleDbType.Date);
                                    
                                    komando.Parameters["@ShohinCd"].Value = SCd;
                                    komando.Parameters["@ShohinName"].Value = SName;
                                    komando.Parameters["@ShohinDate"].Value = SDate;
                                    
                                    
    
                                }
    
                                komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( @ShohinCd, @ShohinName, @ShohinDate )";
    
                                komando.ExecuteNonQuery();
    
                               
                            }
    
    
    インサート文の中の?も@ShohinCdと変更しました。

    これがどこまで正しいのか、要領よく実行できているのか私にはまだまだ全然判断出来ませんが、とりあえず動くようになり、一歩前進です。
    助言を頂いた方々、ありがとうございました。 
    2009年4月30日 6:09
  • komando.Parameters["@SHohinCd"].Value = SCd;
    komando.Parameters["@SHohinName"].Value = SName;
    komando.Parameters["@SHohinDate"].Value = SDate;としました。 ()ではなく []でした。
    そういえば、C# でしたね。VB とごっちゃになっていました。

    解決済みになっていますが、解決しているようには見えません。
    コードには理由のあるものだけを記述するべきです。

    while ループの中で毎回 komando.CommandText に代入するのはなぜですか?(毎回同じですよね?)
    while ループの中で毎回 komando.Parameters に Add するのはなぜですか?(Collection が増え続けませんか?)
    else 側でしかパラメータへの代入をしていないのに、komando.ExecuteNonQuery は if でも else でも通過するのはなぜですか?
    2009年4月30日 6:27
  • while ループの中で毎回 komando.CommandText に代入するのはなぜですか?(毎回同じですよね?)
    while ループの中で毎回 komando.Parameters に Add するのはなぜですか?(Collection が増え続けませんか?)
    else 側でしかパラメータへの代入をしていないのに、komando.ExecuteNonQuery は if でも else でも通過するのはなぜですか?

    またもありがとうございます。

    >komando.ExecuteNonQuery は if でも else でも通過するのはなぜですか?

    ソースを再度デバッグして追いましたが、IFのときは通過しませんでした。

    >while ループの中で毎回 komando.CommandText に代入するのはなぜですか?(毎回同じですよね?)

    レコードを一行ずつ読んでSQLを実行しているので、whileの外へだすと2行レコードがあった場合、最初の1行目のレコードが上書きされてしまいました。

    >while ループの中で毎回 komando.Parameters に Add するのはなぜですか?(Collection が増え続けませんか?)

    すいません。。意味がわかりませんでした。collectionそのものを理解しきれてないです・・・・。
    もう一度検証してみます。

    こういったアドバイスは非常にありがたいです。
    結果としては問題がなくても、ソースが悪いかどうかはまだ自分では判断が出来ませんので。
    大変ありがとうございます。
    2009年4月30日 7:17
  • >komando.ExecuteNonQuery は if でも else でも通過するのはなぜですか?

    ソースを再度デバッグして追いましたが、IFのときは通過しませんでした。
    komand.ExecuteNonQuery を if のときに通過していないとすると、それはそれで問題に思えるのですが。
     
                                if (CSVRow[0].ToString().Equals("ShohinCd"))
                                { }
                                else
                                {
                                    //CSVファイルのレコードをインサート
    
                                    int SCd = int.Parse(CSVRow[0].ToString());
                                    string SName = CSVRow[1].ToString();
                                    DateTime SDate = DateTime.Parse(CSVRow[2].ToString());
    
                                    komando.Parameters.Add("@ShohinCd", OleDbType.Variant);
                                    komando.Parameters.Add("@ShohinName", OleDbType.VarChar);
                                    komando.Parameters.Add("@ShohinDate", OleDbType.Date);
    
                                    komando.Parameters["@ShohinCd"].Value = SCd;
                                    komando.Parameters["@ShohinName"].Value = SName;
                                    komando.Parameters["@ShohinDate"].Value = SDate;
                                }
    
                                komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( @ShohinCd, @ShohinName, @ShohinDate )";
    
                                komando.ExecuteNonQuery();

    通過してますよねぇ...

    >while ループの中で毎回 komando.CommandText に代入するのはなぜですか?(毎回同じですよね?)

    レコードを一行ずつ読んでSQLを実行しているので、whileの外へだすと2行レコードがあった場合、最初の1行目のレコードが上書きされてしまいました。


    何が何に上書きされるのでしょう?

     komando.CommandText への代入は while の外
     komando.ExecuteNonQuery は while の中

    ですよ。

    • 編集済み totojo 2009年4月30日 7:42
    2009年4月30日 7:39
  • 以前アップされたコードに this.shohin_TableTableAdapter.Fill(dataBaseDataSet.Shohin_Table); と
    書いてあるところを見ると、型付 DataSet + TableAdapter(xsd ファイル)を作ってあるように見えますが、
    いかがですか?

    もしそうであれば、ADO.NET のメソッド等を直接操作しなくても、自動生成された DataSet と TableAdapter
    のメソッドを使って、簡単に DB に INSERT できるはずです。

    多分、dataBaseDataSet.Shohin_Table クラスには、ShohinCd, ShohinName, ShohinDate を引数に
    取って Shohin_Table に新たな Row を追加するメソッドが定義されているはずです(メソッドの名前は
    AddShohin_TableRow ではないかと思います)。

    また、shohin_TableTableAdapter クラスには Shohin_Table の修正/追加/削除内容に従って DB を
    更新する Update というメソッドが定義されているはずです。

    AddShohin_TableRow を使って CSV ファイルの各行を Shohin_Table に追加したら、後は
    shohin_TableTableAdapter.Update(dataBaseDataSet.Shohin_Table) というようにすれば、DB に
    INSERT されるはずです。

    検討してみてください。

     

    2009年4月30日 12:26
  • 返信ありがとうございます。

    すいません、今返信に気づきました。

    そして完成コードとして記載したものが間違ってました。ごめんなさい。

    現在は以下のようになってます。
            private void ImportButton_Click(object sender, EventArgs e)
            {
                
                OleDbConnection connect = new OleDbConnection(this.shohin_TableTableAdapter.Connection.ConnectionString);
                connect.Open();
    
                    DataSet CSVDataSet = new DataSet();
                    DataTable CSVTable = new DataTable();
    
                    CSVDataSet.Tables.Add("CSVTable");
    
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinCd", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinName", Type.GetType("System.String"));
                    CSVDataSet.Tables["CSVTable"].Columns.Add("ShohinDate", Type.GetType("System.String"));
    
                    OleDbTransaction transaction = null;
    
                    OleDbCommand komando = new OleDbCommand();
    
                    komando.Connection = connect;
                    //トランザクションの開始
                    transaction = connect.BeginTransaction();
                    komando.Transaction = transaction;
    
                    try
                    {
                       //テーブルのレコードを全削除
                        komando.CommandText = "DELETE FROM Shohin_Table";
                        //CSVを読み込む為のStreamReaderクラスを作成
                        StreamReader reader = new StreamReader(OpenTextBox.Text, Encoding.GetEncoding("Shift_JIS"));
    
                        //Peekメソッド・・次に読み込む文字があるかないかを確認する
                        //        なければー1を返す
                        while (reader.Peek() != -1)
                        {
                            String[] CSVData;
                            CSVData = reader.ReadLine().Split(',');
    
                            //DataSetの作成
                            DataRow CSVRow;
    
                            CSVRow = CSVDataSet.Tables["CSVTable"].NewRow();
                            for (int counter = 0; counter < CSVData.Length; counter++)
                            {
                                CSVRow[counter] = CSVData[counter];
                            }
    
                            CSVDataSet.Tables["CSVTable"].Rows.Add(CSVRow);
    
                            foreach (DataRow CSV in CSVDataSet.Tables["CSVTable"].Rows) ;
                            Console.WriteLine((CSVRow[0]).ToString() + "," + (CSVRow[1]).ToString() + "," + (CSVRow[2]).ToString());
    
                            if (CSVRow[0].ToString().Equals("ShohinCd"))
                            { }
                            else
                            {
                                int SCd = int.Parse(CSVRow[0].ToString());
                                string SName = CSVRow[1].ToString();
                                DateTime SDate = DateTime.Parse(CSVRow[2].ToString());
    
                                //パラメータを作成
                                komando.Parameters.Add("@ShohinCd", OleDbType.Variant);
                                komando.Parameters.Add("@ShohinName", OleDbType.VarChar);
                                komando.Parameters.Add("@ShohinDate", OleDbType.Date);
    
                                //パラメータに値を代入
                                komando.Parameters["@ShohinCd"].Value = SCd;
                                komando.Parameters["@ShohinName"].Value = SName;
                                komando.Parameters["@ShohinDate"].Value = SDate;
    
                                komando.CommandText = "INSERT INTO Shohin_Table ( ShohinCd, ShohinName, ShohinDate ) VALUES ( @ShohinCd, @ShohinName, @ShohinDate )";
                                //SQLを実行
                                komando.ExecuteNonQuery();
                                
                            }
    
                        }
                            OpenTextBox.Clear();
                            reader.Close();
    
                        }
    
                        catch (System.Exception)
                        {
                            if (transaction != null)
                            {
                                transaction.Rollback();
                                //komando.Transaction.Rollback();
                                transaction.Dispose();
                                transaction = null;
                            }
                            System.Windows.Forms.MessageBox.Show("エラーだよ");
                        }
                        finally
                        {
                            // 正常の場合はコミット
                            if (transaction != null)
                            {
                                //コミット
                                komando.Transaction.Commit();
    
                                //コミットした結果をグリッドに表示させる
                                this.shohin_TableTableAdapter.Fill(dataBaseDataSet.Shohin_Table);
    
                                MessageBox.Show("CSVファイルを取り込みました。");
    
                                transaction.Dispose();
                                transaction = null;
                            }
                        }
            }
    2009年5月1日 8:15
  • 返信ありがとうございます。

    TableAdapterを使ってのインサートは出来ました。

    勉強中ということでソースが簡単なのでご指摘の通りなんですが、今回は練習・基本的事項の理解ということで
    こちらの方法でやらせて頂きました。

    おかげさまで色々と勉強になっております。

    ありがとうございます。
    2009年5月1日 8:31
  • > 返信ありがとうございます。

    誰に対してレスされているかはっきりしませんが、私に対するレスと理解して・・・

    > 勉強中ということでソースが簡単なのでご指摘の通りなんですが、今回は練習・基本的事項の理解ということで
    > こちらの方法でやらせて頂きました。

    それはそれで結構なんですが、あらかじめその旨言っておいていただくと、回答が余計なお世話にならずに
    済みます。

    で、「練習・基本的事項の理解」ということですが、アップされたコードを見る限りその目的は果たされて
    いないようです。失礼かもしれませんが、はっきり言わせていただければ、これで動くほうが不思議という
    感じです。

    「理解」を深める気持ちがありましたら、以下の点を検討してみてください。

    (1) totojo さんの言われるように komando.Parameters.Add などの位置を検討する。

    (2) 例外処置をきちんとやる。以下のサイトが参考になると思います。

        .NETの例外処理 Part.1
        http://blogs.msdn.com/nakama/archive/2008/12/29/net-part-1.aspx

        .NETの例外処理 Part.2
        http://blogs.msdn.com/nakama/archive/2009/01/02/net-part-2.aspx

    (3) 型付 DataSet + TableAdapter、普通の DataSet 両方を使っているが、中途半端に使わない。
      その機能を 100% 利用しないなら無駄ですので、まったく使わないように考えてみてください。

    2009年5月2日 2:05
  • SurferOnWwwさま

    何度もありがとうございます。

    新しいプロジェクトが始まってしまい、たくさんのアドバイス・ご指摘を受けている中、大変恐縮ですが
    上記でのご指摘の通り、中途半端な理解のままモノ作りをはじめることになりました。
    (ちなみに、私はプログラミング未経験から始めた1年生です。)

    たくさん頂いた助言を基にSurferOnWwwさん がまとめて頂いた3件も含め
    一生懸命勉強しながら取り組んでいきたいと思います。

    >
    で、「練習・基本的事項の理解」ということですが、アップされたコードを見る限りその目的は果たされて
    >いないようです。失礼かもしれませんが、はっきり言わせていただければ、これで動くほうが不思議という
    >感じです。

    うーん、なに故でしょうか。とりあえず問題なく動いてはいるんですが・・。
    今のプロジェクトを進めながらもっとキレイになるように先にあげたソースの方も
    もっとよく考えてみます。

    ありがとうございました。
    2009年5月4日 7:02