我目前有一个“过滤器”对象,它对应一个业务对象。此对象具有与我希望能够过滤/搜索此类业务对象列表的不同方式相关的属性。目前,这些Filter对象有一个方法,用于构建where子句的内容,然后将其传递给SQL Server 2000存储过程,并在其中与其余的select查询进行连接。然后使用 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 ");
}
答案 0 :(得分:3)
由于计划重用,sp_executesql优于exec,并且您可以使用有助于反对sql注入的参数。如果使用正确,sp_executesql也不会导致过程缓存膨胀
看看这两篇文章
Avoid Conversions In Execution Plans By Using sp_executesql Instead of Exec
Changing exec to sp_executesql doesn't provide any benefit if you are not using parameters correctly
答案 1 :(得分:3)
是的,sp_executesql将“缓存”它执行的查询的执行计划。
或者,不是将部分查询传递给存储过程,在那里构建完整查询,并执行动态SQL,而是可以在.NET端构建整个查询并使用ADO.NET命令对象执行它。通过ADO.NET执行的所有查询都默认为“缓存”。
答案 2 :(得分:1)
您应该使用sp_executesql,因为正如您所说,存储查询计划并优化将来的执行。它通常似乎比执行更好地处理动态sql。
答案 3 :(得分:0)
现代RDBMS(无法真正说是否将SQL Server 2000视为“现代”)已经针对ad-hoc查询进行了优化,因此可以忽略不计的性能(如果有的话)。困扰我的是你正在使用sproc构建动态SQL:这是一个巨大的调试/支持PITA。
答案 4 :(得分:0)
sp_executesql是更好的选择。您是否考虑过不使用存储过程或至少取消一些动态?我认为任何一种注射都会更安全。我写的过滤器就像你在谈论的那样,但是我试着在我的代码中处理输入,而不是在存储过程中。我真的很喜欢动态sql,但有时候更加安全。