0

我正在尝试根据查询字符串参数动态创建 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 语句?

4

3 回答 3

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。

于 2013-06-24T15:36:34.943 回答
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;
于 2013-06-24T15:55:03.600 回答
0

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

下面是使用实体框架的代码示例。在此示例中,按照您的示例,我们使用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 将比 稍微复杂一点SELECT * from Items AND item_price < 100,因为它取决于 SQL 生成器来创建它。

于 2013-12-02T00:09:44.263 回答