使用ASP.NET中的查询字符串参数形成动态SQL语句

时间:2013-06-24 15:25:48

标签: asp.net sql sql-server-2008

我正在尝试根据查询字符串参数动态创建MS SQL查询。

我目前正在使用请求任何有效查询字符串参数值的变量:如果参数不为空,则该变量构成SQL语句的一部分。如果为空,则变量保持空白。

例如:

 var search = Request["search"].IsEmpty() ? "" : Request["search"];
 var price = Request["price"].IsEmpty() ? "" : Request["price"];

 string searchSQL = "WHERE item_name LIKE '%" + search + "%'";
 string priceSQL = " AND item_price < " + price;

 string sql = "SELECT * from Items " + searchSQL + priceSQL;

如果两个查询参数都有效,则此sql查询运行正常。但是如果搜索参数为空且价格不是,则sql查询将变为无效:

SELECT * from Items AND item_price < 100

我的计划是使用最多6个不同的查询字符串参数,因此无法真正使用此代码段。这种方法的最佳实践是什么?是否有可能以这种方式创建有效的动态sql语句?

3 个答案:

答案 0 :(得分:2)

您可以使用null参数:

select *
from items
where (@name is null or item_name like '%' + @name + '%')
  and (@price is null or item_price < @price)";

然后你要添加参数,并为那些尚未给出的值指定null值,这将使WHERE语句的那部分不过滤任何东西,你不必建立每次都有不同的SQL。

答案 1 :(得分:2)

就个人而言,Lasse V. Karlsen的方法是我倾向于使用的方法,虽然我有一个应用程序,我使用动态SQL根据用户想要做的事情生成更有效的查询(即少加入时,我可以逃脱它)。如果您确实对动态SQL进行了设置,则可以使用三元运算符来进行更好的查询:

string search = Request("search").IsEmpty() ? "" : Request("search");
decimal price = Request("price").IsEmpty() ? "" : Request("price");
string param3 = Request("param3").IsEmpty() ? "" : Request("param3");
string param4 = Request("param4").IsEmpty() ? "" : Request("param4");
string param5 = Request("param5").IsEmpty() ? "" : Request("param5");
string param6 = Request("param6").IsEmpty() ? "" : Request("param6");

string whereClause = "";

whereClause += whereClause.length > 0 & search.length > 0 ? " AND item_name LIKE '%' + @search + '%'" : "WHERE item_name LIKE '%' + @search + '%'";
whereClause += whereClause.length > 0 & search.length > 0 ? " AND item_price < @price" : "WHERE item_price < @price";
whereClause += whereClause.length > 0 & search.length > 0 ? " AND param3 = @param3" : "WHERE param3 = @param3";
whereClause += whereClause.length > 0 & search.length > 0 ? " AND param4 = @param4" : "WHERE param4 = @param4";
whereClause += whereClause.length > 0 & search.length > 0 ? " AND param5 = @param5" : "WHERE param5 = @param5";
whereClause += whereClause.length > 0 & search.length > 0 ? " AND param6 = @param6" : "WHERE param6 = @param6";

string sql = "SELECT * from Items " + whereClause;

SqlConnection conn = new SqlConnection("your connection string");
SqlCommand cmd = new SqlCommand(sql, conn);

// fill in all parameters (even ones that may not exist)
cmd.Parameters.Add("search", SqlDbType.VarChar, 50).Value = search;
cmd.Parameters.Add("price", SqlDbType.Float).Value = price;
cmd.Parameters.Add("param3", SqlDbType.VarChar, 50).Value = param3;
cmd.Parameters.Add("param4", SqlDbType.VarChar, 50).Value = param4;
cmd.Parameters.Add("param5", SqlDbType.VarChar, 50).Value = param5;
cmd.Parameters.Add("param6", SqlDbType.VarChar, 50).Value = param6;

答案 2 :(得分:0)

如果您要将应用程序转换为使用Entity FrameworkLinq2Sql(或类似的ORM框架)。您可以在代码中构建查询,然后将其发送到数据库。

下面是使用Entity Framework的代码示例。在此示例中,按照您的示例,我们使用DbSet<Item>中的DbContext。它继承了IQueryable<Item>,它也是许多扩展方法的返回类型,例如Where。我们现在可以将一系列where语句链接在一起,以创建所需的查询。

using (MyDbContext db = new MyDbContext())
{
    IQueryable<Item> items = db.Items;

    if (!string.IsNullOrEmpty(itemName))
        items = items.Where(s => s.Name.Contains(itemName));

    if (maxPrice > 0)
        items = items.Where(s => s.Price < maxPrice);

    // Get results
    List<Item> results = items.ToList();
}

但请注意,SQL generatede将比SELECT * from Items AND item_price < 100更复杂,因为要由SQL Generator创建它。