我正在构建一个复杂的查询以在 Web 视图中显示一些统计结果。根据用户的选择,视图可以有几个不同的过滤器。此外,还可以使用通配符。
我正在使用 SqlParameters 在 c# 中以编程方式构建此查询。所以查询看起来像这样:
sc.CommandText = "SELECT * FROM table
WHERE field1 = @filter1
AND field2 LIKE @filter2"; //...and more parameters
sc.SqlParameters.Add(
new SqlParameter("@filter1", SqlDbType.Int, 32) { Value = 1});
sc.SqlParameters.Add(
new SqlParameter("@filter2", SqlDbType.VarChar, 446) { Value = "whatever%"});
这是一个非常简化的版本,但查询本身并不是重点。请记住,它可以有不同的可选参数(我认为这是很常见的情况)。
当我在 Sql Manager 中运行此查询时,我意识到使用参数时速度非常慢。因此,以下两个查询应该是相同的,它们使用不同的执行计划,这使得参数化的查询运行速度慢很多:
DECLARE @filter1 INT
DECLARE @filter2 VARCHAR 446
SET @filter1 = 1
SET @filter2 = "whatever%"
SELECT * FROM table WHERE field1 = @filter1 AND field2 LIKE @filter2
快速版本:
SELECT * FROM table WHERE field1 = 1 AND field2 LIKE 'whatever%'
这是另一个有同样问题的人的例子:
似乎有一种叫做参数嗅探的东西,它可能会使参数化查询运行得更慢,但它不适用于我的情况,因为这不是存储过程。
提出的解决方案之一是使用 OPTION(RECOMPILE) 或 OPTION(OPTIMIZE FOR)。我不能这样做,因为我有大约 10 个可选参数,它们可能在过滤器中或不在过滤器中,并且在使用LIKE
.
所以,我觉得我陷入了死胡同,我正在考虑摆脱参数并在代码上构建动态文字查询。但随后 Sql Injection 出现在游戏中。
那么,您对如何解决此问题还有其他建议吗?或者你知道一种安全的方法来逃避参数吗?
编辑:在这里,您可以使用一个参数查看查询的执行计划LIKE
:
编辑:更简化的代表性查询执行计划: