2013-06-24 39 views
0

我正在尝试基于查询字符串参数动态创建MS SQL查询。在ASP.NET中使用查询字符串参数形成动态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语句?

+2

最佳做法至少从使用参数开始。 –

回答

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。

+0

谢谢,这是一个非常简单的解决方案,效果很棒! – mmmoustache

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; 
+0

谢谢你的回答,皮特!尽管如此,你的答案仍然有帮助,我会试验这两种方法,看看在这种情况下什么效果最好! – mmmoustache

0

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

下面是使用实体框架的代码示例。在本例中,按照您的示例,我们使用DbContext中的DbSet<Item>。它继承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生成器来创建此。

相关问题