使用CASE或其他方法在两个SQL语句之间进行选择

时间:2014-04-03 20:05:18

标签: asp.net sql sql-server

我有一个下拉列表,我想在运行SQL命令之前先检查所选的值,所以这是我的逻辑:如果下拉列表的选定值不是'ALL'那么我想运行这个sql语句:

select distinct Location 
from myTable 
where PROGRAM = '"+program+'"

否则,如果下拉列表的选定值设置为'ALL',那么我想改为运行此SQL命令:

select distinct Location 
from myTable

这是我的代码,它的工作正常,但不是我希望它工作的方式。如何修改SQL命令以便检查上面提到的条件?感谢

protected void BindServiceList(DropDownList ddlService)
{
        DropDownList ddl = (DropDownList)GV_MJJ.HeaderRow.FindControl("ddlProgram");

        string program = ddl.SelectedValue;
        String strConnString = System.Configuration.ConfigurationManager
                    .ConnectionStrings["myConn"].ConnectionString;

        SqlConnection con = new SqlConnection(strConnString);
        SqlDataAdapter sda = new SqlDataAdapter();

        SqlCommand cmd = new SqlCommand("select distinct LOCATION" +
                        " from myTable where PROGRAM = '" + program + "' ");
        cmd.Connection = con;

        con.Open();

        ddlService.DataSource = cmd.ExecuteReader();
        ddlService.DataTextField = "LOCATION";
        ddlService.DataValueField = "LOCATION";

        ddlService.DataBind();

        con.Close();

        ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
                .Selected = true; 
}

3 个答案:

答案 0 :(得分:3)

不要更改SQL命令,而是根据条件创建不同的SQL命令文本。此外,您应该使用SqlParameter而不是字符串连接。您的代码很容易SQL injection。考虑在using statement中包含您的连接和命令对象,因为这将确保在块结束时处理资源。

using (SqlConnection con = new SqlConnection(strConnString))
{
    SqlDataAdapter sda = new SqlDataAdapter();

    using (SqlCommand cmd = new SqlCommand())
    {
        if (program.Equals("All", StringComparison.InvariantCultureIgnoreCase))
        {
            cmd.CommandText = "select distinct LOCATION from myTable";
        }
        else
        {
            cmd.CommandText = "select distinct LOCATION from myTable WHERE PROGRAM = @program";
            cmd.Parameters.AddWithValue("@program", program);
        }
        cmd.Connection = con;
        con.Open();
        ddlService.DataSource = cmd.ExecuteReader();
        ddlService.DataTextField = "LOCATION";
        ddlService.DataValueField = "LOCATION";
        ddlService.DataBind();
        con.Close(); // can be left out because of `using` statement
        ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
                .Selected = true;
    }
}

答案 1 :(得分:2)

这样做:

protected void BindServiceList(DropDownList ddlService)
{
    DropDownList ddl = (DropDownList)GV_MJJ.HeaderRow.FindControl("ddlProgram");
    string program = ddl.SelectedValue;
    String strConnString = System.Configuration.ConfigurationManager
                .ConnectionStrings["myConn"].ConnectionString;
    using (var con = new SqlConnection(strConnString) )
    using (var cmd = new SqlCommand("select distinct LOCATION from myTable where PROGRAM LIKE @Program", con) )
    {
         //guessing at column type/length here
         cmd.Parameters.Add("@Program", SqlDbType.NVarChar, 20).Value = program;

        con.Open();
        ddlService.DataSource = cmd.ExecuteReader();
        ddlService.DataTextField = "LOCATION";
        ddlService.DataValueField = "LOCATION";
        ddlService.DataBind();
    }
    ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
            .Selected = true; 
}

请注意我修复了你的sql注入漏洞!另请注意,我已将=更改为LIKE。然后,您可以将value控件中All项的ddlProgram属性设置为:%。 (如果在使用数据绑定ddl时需要帮助,请参阅AppendDataBoundItems属性。将该通配符与LIKE运算符一起使用将导致查询返回所有位置。

答案 2 :(得分:0)

首先Parameterize您的查询。

由于已有使用c#的解决方案。我将提出一个SQL解决方案。

您可以通过传递一个表明下拉值是Case的参数,在WHERE CLause中执行ALL。 类似的东西:

SELECT DISTINCT Location
FROM myTable
WHERE (
        CASE 
            WHEN @IsAllSelected = 0
                THEN PROGRAM
            WHEN @IsAllSelected = 1
                THEN 1
            END
        ) = (
        CASE 
            WHEN @IsAllSelected = 0
                THEN @Your_program_value
            WHEN @IsAllSelected = 1
                THEN 1
            END
        )