如何防止在表中允许空值

时间:2016-07-21 15:46:12

标签: c# asp.net sql-server

我有一个程序,其中有11个变量需要插入到SQL 2008 Express DB中。所有工作都可以,直到可以为NULL的变量为NULL。然后SQL没有获取数据。这是我的代码,并感谢所有可以提供帮助:

 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";
       }

3 个答案:

答案 0 :(得分:2)

以下内容不是您的问题的答案,而是您的代码滥用Ado.Net的所有地方的示例。尝试以这种方式重构您拥有的任何ado.net代码。我同意这些评论,你的一般方法可能是错误的,但是这些是你可能从其余代码中受益的一般指示。指针是。

  • 始终使用块
  • 包装SqlConnections
  • 始终使用参数化查询
    • 始终指定参数SqlDbType(显然使用SqlServer时
    • 始终使用正确的参数类型而不是添加字符串值

重构了ado.net代码

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();
        }
    }
}

答案 1 :(得分:1)

您应该重新考虑如何从电子表格中读取数据。显然你把整张表放到一个大的DataTable中,然后迭代这个。您应该拆分数据区域,这样您只需将前两列读入一个DataTable,将剩余的五列读入另一个DataTable。然后分别迭代两个DataTable并将包含的行保存到数据库中。

如果您真的只想禁止创建具有空值的行,则可以在执行插入之前简单地检查null值。

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

另外还有一些提示:

  1. 查看参数化和准备好的查询,它们可以使您的代码更加安全。
  2. 您无需为每个命令打开和关闭sql连接。您可以在循环之前打开它,创建并执行一些命令,并在循环结束后关闭它,直到完成。
  3. 您缺少数据的第一行。 c#中的绝大多数集合都从索引0开始。
  4. 修改

    对于您的请求,我将空检查添加到您的代码中。 但我真的不认为你应该这样做!就像我上面提到的那样,你应该将你的数据表分成两个表,这样每个表只包含相关的行。你应该看看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();
                }
            }
        } 
    

答案 2 :(得分: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