0

我目前有一个对应于业务对象的“过滤器”对象。此对象具有与我希望能够过滤/搜索此类业务对象列表的不同方式相关的属性。目前,这些过滤器对象有一个方法,该方法构建 where 子句的内容,然后将其传递到 SQL Server 2000 存储过程,在该存储过程中与选择查询的其余部分连接。然后使用Exec执行最终字符串。

目前这工作正常,除了我担心缺乏执行计划缓存的性能问题。在一些研究中,我看到了调用sp_executesql的用法;这是一个更好的解决方案还是对我正在做的事情有更好的约定?

更新:我认为使用 sp_executesql 的部分问题是基于我的过滤器中的一个集合,我需要生成一个 OR 语句列表。我不确定“参数化”查询是否是我的解决方案。

例子

    var whereClause = new StringBuilder();
    if (Status.Count > 0)
    {
       whereClause.Append("(");
       foreach (OrderStatus item in Status)
       {
          whereClause.AppendFormat("Orders.Status = {0} OR ", (int)item);
       }          

       whereClause.Remove(whereClause.Length - 4, 3);
       whereClause.Append(") AND ");
    }
4

5 回答 5

3

sp_executesql 由于计划重用而优于 exec,并且您可以使用有助于防止 sql 注入的参数。如果正确使用 sp_executesql 也不会导致过程缓存膨胀

看看这两篇文章

通过使用 sp_executesql 而不是 Exec 来避免执行计划中的转换

如果您没有正确使用参数,将 exec 更改为 sp_executesql 不会带来任何好处

于 2009-06-18T13:56:49.590 回答
3

是的,sp_executesql 将“缓存”它执行的查询的执行计划。

或者,您可以在 .NET 端构建整个查询并使用 ADO.NET 命令对象执行它,而不是将部分查询传递给存储过程、在那里构建完整查询并执行动态 SQL。默认情况下,通过 ADO.NET 执行的所有查询都被“缓存”。

于 2009-06-18T14:00:24.357 回答
1

您应该使用 sp_executesql,因为正如您所说,查询计划已存储并且未来的执行将得到优化。它通常似乎也比执行更好地处理动态 sql。

于 2009-06-18T13:56:26.690 回答
0

现代 RDBMS(不能真正说是否将 SQL Server 2000 视为“现代”)针对即席查询进行了优化,因此对性能的影响可以忽略不计(如果有的话)。困扰我的是您正在使用 sproc 构建动态 SQL:这是一个巨大的调试/支持 PITA。

于 2009-06-18T13:56:25.100 回答
0

sp_executesql 是更好的选择。您是否考虑过为此不使用存储过程,或者至少去掉一些动态?我认为任何形式的注射都会更安全。我编写过滤器的方式很像您所说的,但我尝试处理代码中的输入,而不是存储过程中的输入。我真的很喜欢动态 sql,但有时加倍努力可能更安全。

于 2009-06-18T14:03:21.450 回答