有没有更有效的方法来编写这个SQL代码?

时间:2016-02-11 18:20:26

标签: c# mysql

protected void Button1_Click(object sender, EventArgs e)
{
    MySqlConnection connection = new MySqlConnection(ConfigurationManager.ConnectionStrings["myconstring"].ConnectionString);
    connection.Open();
    symptons = String.Join(", ", CheckBoxList1.Items.Cast<ListItem>().Where(i => i.Selected).Select(i => i.Value).ToArray());
    Label3.Text = symptons;
    if(symptons!="")
    {
        MySqlCommand cmd = new MySqlCommand("select d.dname from disease d inner join diseasesymptom ds on ds.did = d.did inner join symptom s on s.sid = ds.sid where s.sname in (" + symptons + ")", connection);
        using (MySqlDataAdapter sda = new MySqlDataAdapter())
        {
            cmd.Connection = connection;
            sda.SelectCommand = cmd;
            using (DataTable dt = new DataTable())
            {
                sda.Fill(dt);
                GridView1.DataSource = dt;
                GridView1.DataBind();
            }
        }
    }
    else
    {
        Label2.Text = "select at least one symptom";
    }      
}

我知道我在自己的代码上执行sql注入,所以如何防止这种情况, 基本上有3个表:

  1. disease_table [columns =](disease_id,disease_name)
  2. symptom_table [columns =](symptom_id,symptom_name)
  3. disease_symptom [columns =](disease_id,symptom_id)
  4. 我的网页上有一个复选框列表,其中的症状是text = fever,value ='fever'..等等这样做的原因是用户可以选择任意数量的复选框,并且in子句不接受参数

1 个答案:

答案 0 :(得分:0)

与评论中的建议相反,您不需要存储过程来防止SQL注入。您可以使用parameterized queries来查看。

以下代码应该完成这项工作:

MySqlCommand cmd = new MySqlCommand();
cmd.Connection = connection;

List<string> names = new List<string>();
for (int i = 0; i < symptons.Length; i++)
{
    names.Add("@Param_" + i);
    cmd.Parameters.Add(new MySqlParameter("@Param_" + i, symptons[i]));
}
cmd.CommandText = "select d.dname from disease d inner join diseasesymptom ds on ds.did = d.did inner join symptom s on s.sid = ds.sid where s.sname in (" + string.Join(",", names) + ")"; 

基本上,您不会注入值,而是为查询注入参数。参数名称在您的代码中生成,因此无法与之混淆。在执行查询之前,驱动程序会对参数的值进行清理,这样就不会对这些参数进行消隐。