2016-07-21 6 views
-1

私は、SQL 2008 Express DBに挿入する必要のある11個の変数を持つプログラムを持っています。すべての変数は、NULLになる可能性のある変数がNULLになるまで動作します。その後、SQLはデータを取得しません。ここに私のコードがあり、助けてくれれば幸いです。テーブルにNULL値を許可しないようにする方法

private void PostDatatoServer() 
     { 
      String connectionString = @"Data Source=LUCKYTIGER\SQLEXPRESS;Initial Catalog=John;Integrated Security=True"; 
      SqlConnection con = new SqlConnection(connectionString); 
      con.Open(); 
      textBox1.Text = "Connection made"; 
      SqlCommand cmd = con.CreateCommand(); 
      string str = ""; 
      str += "INSERT INTO Parsed(Date, Gal, Sys, Sl, ST, PN, PlayN, Sym, Rk, All, Rel)"; 
      str += "VALUES(@Date, @Gal, @Sys, @Sl, @ST, @PN, @PlayN, @Sym, @Rk, @All, @Rel)"; 
      SqlCommand cmd = new SqlCommand(str, con); 
      cmd.CommandType = CommandType.Text; 
      cmd.Parameters.Add(new SqlParameter("@Date", uegParser.strTime)); 
      cmd.Parameters.Add(new SqlParameter("@Gal", Convert.ToInt16(uegParser.strGalaxyNum))); 
      cmd.Parameters.Add(new SqlParameter("@Sys", Convert.ToInt16(uegParser.strSystemNum))); 
      cmd.Parameters.Add(new SqlParameter("@Sl", uegParser.intSlot)); 
      cmd.Parameters.Add(new SqlParameter("@ST", uegParser.intSlotType)); 
      if (uegParser.strPlanetName == "") 
       cmd.Parameters.Add(new SqlParameter("@PN", SqlDbType.NVarChar).Value = DBNull.Value); 
      else 
       cmd.Parameters.Add(new SqlParameter("@PN", uegParser.strPlanetName)); 
      if (uegParser.strPlayerName == "") 
      { 
       cmd.Parameters.Add(new SqlParameter("@PlayN", DBNull.Value)); 
       TextBox2.Text = "Null player name"; 
      } 
      else 
      { 
       cmd.Parameters.Add(new SqlParameter("@PlayN", uegParser.strPlayerName)); 
      } 
      if (uegParser.strSymbols == "") 
       cmd.Parameters.Add(new SqlParameter("@Sys", DBNull.Value)); 
      else 
       cmd.Parameters.Add(new SqlParameter("@Sym", uegParser.strSymbols)); 
      if (uegParser.strRank == "") 
       cmd.Parameters.Add(new SqlParameter("@Rk", DBNull.Value)); 
      else 
       cmd.Parameters.Add(new SqlParameter("@Rk", uegParser.strRank)); 
      if (uegParser.strAlliance == "") 
       cmd.Parameters.Add(new SqlParameter("@All", DBNull.Value)); 
      else 
       cmd.Parameters.Add(new SqlParameter("@All", uegParser.strAlliance)); 
      cmd.Parameters.Add(new SqlParameter("@Rel", uegParser.intRelationship)); 

      cmd.ExecuteNonQuery(); 
      con.Close(); 
      TextBox2.Text = "Connection closed"; 
     } 
+2

null値が発生した場合はどうしますか?挿入を防止する?デフォルト値を挿入しますか? – derpirscher

+1

列を 'NOT NULL'として宣言するか、' NOT NULL'制約を追加してください。 –

+2

1つの大きなこと:SQLインジェクションを防ぐためにパラメータを使用してください!... –

答えて

1

スプレッドシートからデータを読み取る方法を再考する必要があります。どうやら、シート全体を1つの大きなDataTableに入れて、これを繰り返します。最初の2つの列を1つだけDataTableに、残りの5つの列を2番目のDataTableに読み込むように、データ結合を分割する必要があります。次に、2つのDataTableを別々に反復処理し、含まれている行をデータベースに保存します。

null値を持つ行を作成したくない場合は、挿入する前にnull値をチェックするだけです。

if (!String.IsNullOrEmpty(Id) && !String.IsNullOrEmpty(Name)) { 
    cmd = new SqlCommand(....); 
    cmd.ExecuteNonQuery(); 
} 

さらにいくつかのヒント:

  1. はパラメータ化し、準備されたクエリを見てみましょう、彼らはあなたのコードがたくさんより安全に。
  2. 単一のコマンドごとにSQL接続を開いたり閉じたりする必要はありません。ループの前に開いて、いくつかのコマンドを作成して実行し、ループが終了したらそれを閉じることができます。
  3. データの最初の行がありません。 C#でコレクションの大半は、インデックス0

EDITあなたの要求のために

で始まり、私はあなたのコードにはnullチェックを追加しました。 しかし、私は本当にあなたがそれをこのようにすべきだとは思わない!上記のように、データテーブルを2つのテーブルに分割し、それぞれに関連する行のみが含まれるようにする必要があります。パラメータ化されたクエリを作成する方法については、Igorの答えをご覧ください。また、上記のヒントを考慮に入れてください。そして最後に、私は失礼を意味するわけではありませんが、あなたは本当に良い本やウェブからのチュートリアルを手に入れて基礎を学ぶべきです。そうすればあなたの質問への悩みを理解することができます。

protected void btn_insert_Click(object sender, EventArgs e) 
    { 

     DataSet ds = new DataSet(); 
     ds = (DataSet)Session["DTset"]; 

     for (int i = 1; i < ds.Tables[0].Rows.Count; i++) 
     { 

      string Id = ds.Tables[0].Rows[i][0].ToString(); 
      string Name = ds.Tables[0].Rows[i][1].ToString(); 

      SqlConnection con = new SqlConnection(connStr); 
      SqlCommand cmd; 
      if (!string.IsNullOrEmpty(Id) && !string.IsNullOrEmpty(Name)) { 
       cmd = new SqlCommand("insert into tbl1(ID,Name) values ('" + Id + "','" + Name + "')", con); 
       con.Open(); 
       int j= cmd.ExecuteNonQuery(); 
       con.Close(); 
      } 

      string Id1 = ds.Tables[0].Rows[i][2].ToString(); 
      string Name1 = ds.Tables[0].Rows[i][3].ToString(); 
      string VehicleTypeId = ds.Tables[0].Rows[i][4].ToString(); 
      string VehicleType = ds.Tables[0].Rows[i][5].ToString(); 
      string Capacity = ds.Tables[0].Rows[i][6].ToString(); 


      if (!string.IsNullOrEmpty(Id1) && !string.IsNullOrEmpty(Name1) && !string.IsNullOrEmpty(VehicleTypeId) && !string.IsNullOrEmpty(VehicleType) && !string.IsNullOrEmpty(Capacity)) { 
       string InsQuery = "insert into tbl2(Id,Name,Subject,status,review) values ('" + Id1 + "','" + Name1 + "','" + Subject+ "','" + status+ "','" + review+ "')"; 
       cmd = new SqlCommand(InsQuery,con); 
       con.Open(); 
       int k= cmd.ExecuteNonQuery(); 
       con.Close(); 
      } 
     } 
    } 
+0

@Igorの答え – derpirscher

+0

でパラメータ化されたクエリを作成する方法をご覧ください。最初にnullをクエリし、最初のクエリを実行します。 2番目のクエリの値に対しても同じ処理を行い、これらの値がnullでない場合は、2番目のクエリ – derpirscher

2

次は、あなたの質問への答えが、あなたのコードはAdo.Netを乱用しているすべての場所の例ではありません。この方法で持っているADNコードを再構成しようとします。私はコメントに同意する、あなたの一般的なアプローチはおそらく間違っていますが、これらはあなたのコードの残りの部分でおそらく恩恵を受けることができる一般的なポインタです。ポインタがあります。

  • 常に必ず(明らかをのSQLServerを使用する場合)常にパラメータは、SqlDbTypeを指定するパラメータ化クエリ
    • を使用ブロック
    • を使用してSqlConnectionsラップ
    • 常に正しいパラメータタイプを使用する代わりに文字列を追加します値

リファクタリング済み。ネットコード

protected void btn_insert_Click(object sender, EventArgs e) 
{ 
    DataSet ds = new DataSet(); 

    // i would not use Session unless necessary but that is out of scope for the question 
    // also do not forget to dispose the datatabale when finished and remove it from the session 
    ds = (DataSet)Session["DTset"]; 


    // always wrap your SqlConnection in a using block 
    // it ensures the connection is always released 
    // also there is no reason to have this inside the loop 
    // there is no reason to close/reopen it every time 
    using(SqlConnection con = new SqlConnection(connStr)) 
    { 
     con.Open(); // open once 
     for (int i = 1; i < ds.Tables[0].Rows.Count; i++) 
     { 
      // do not convert everything to strings, pick the correct type as it is in the table or convert it to the correct type if the table contains only strings 
      string Id = ds.Tables[0].Rows[i][0].ToString(); 
      string Name = ds.Tables[0].Rows[i][1].ToString(); 

      cmd = new SqlCommand("insert into tbl1(ID,Name) values (@ID,@Name)"; 
      cmd.Parameters.AddWithValue("@ID", Id).SqlDbType = SqlDbType.; // pick the correct dbtype 
      cmd.Parameters.AddWithValue("@Name", Name).SqlDbType = SqlDbType.; // pick the correct dbtype 
      int j= cmd.ExecuteNonQuery(); 

      // do not convert everything to strings, pick the correct type as it is in the table or convert it to the correct type if the table contains only strings 
      string Id1 = ds.Tables[0].Rows[i][2].ToString(); 
      string Name1 = ds.Tables[0].Rows[i][3].ToString(); 
      string VehicleTypeId = ds.Tables[0].Rows[i][4].ToString(); 
      string VehicleType = ds.Tables[0].Rows[i][5].ToString(); 
      string Capacity = ds.Tables[0].Rows[i][6].ToString(); 

      string InsQuery = "insert into tbl2(Id,Name,Subject,status,review) values (@Id,@Name,@Subject,@status,@review)"; 
      cmd = new SqlCommand(InsQuery,con); 
      cmd.Parameters.AddWithValue("@id", Id1).SqlDbType = SqlDbType.; // pick the correct dbtype 
      cmd.Parameters.AddWithValue("@Name", name1).SqlDbType = SqlDbType.; // pick the correct dbtype 
      // add the rest of your parameters here 

      int k= cmd.ExecuteNonQuery(); 
     } 
    } 
} 
+0

@ user6429940を実行します。これは、値を割り当てる列のデータ型です。その列挙型は、 'Int'や' BigInt'や 'Varchar'のような正しい値を使って完成させるだけです。 – Igor

+0

@ user6429940 - これに基づいて' id'の例があります残りの部分は、 'cmd.Parameters.AddWithValue(" @ ID "、Id).SqlDbType = SqlDbType.Int;'( 'Int'を追加したことに気付く)。可能なすべての列挙値の一覧については、[SqlDbType](https://msdn.microsoft.com/en-us/library/system.data.sqldbtype(v = vs.110).aspx) – Igor

+0

@ user6429940を参照してください。列挙を見て? varXXX(varcharのような)の長さは 'SqlParameter'の別のプロパティであり、' AddWithValue'を使って設定することはできませんが、おそらくそれは必要ありません。 – Igor

0

フールプルーフソリューション:SQLストアドプロシージャを使用します。

--sql 
create procedure dbo.Parsed_i 
    @Date datetime, 
    @Gal int, 
    --so on 
    @PN nvarchar(100) = null --default value 
    --so on 
as 
INSERT INTO Parsed(Date, Gal, Sys, Sl, ST, PN, PlayN, Sym, Rk, All, Rel) 
VALUES(@Date, @Gal, @Sys, @Sl, @ST, @PN, @PlayN, @Sym, @Rk, @All, @Rel) 

//C# 
//... 
SqlCommand cmd = new SqlCommand("dbo.Parsed_i", con); 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Parameters.Add("@ST", SqlDbType.Int).Value = uegParser.intSlotType; 
if (!string.IsNullOrEmpty(uegParser.strPlanetName)) 
    cmd.Parameters.Add("@PN", SqlDbType.NVarChar).Value = uegParser.strPlanetName; 
//note: no **else** part 
//so on 
関連する問題