Sqlserver 2005中动态查询的缺点?

时间:2010-05-11 07:17:28

标签: sql tsql stored-procedures query-optimization

我在我的数据库中使用了很多动态查询程序,因为我的过滤器没有修复,所以我把@filter作为参数并传入了程序。

Declare @query as varchar(8000)
Declare @Filter as varchar(1000)

set @query = 'Select * from Person.Address where 1=1 and ' + @Filter

exec(@query)

就像我的过滤器包含表中的任何字段以进行比较。

这会影响我的表现吗? 有没有其他方法来实现这类事情

3 个答案:

答案 0 :(得分:2)

对于性能,问题仅在于数据库是否可以重用现有计划。

简单来说,您可以看到它,因为数据库使用sql语句作为键来缓存查询计划。一旦更改了sql语句,它就不会在缓存中,并且必须生成新的计划。

因此生成像

这样的动态语句
"SELECT * FROM table WHERE param = @paramvalue"

更有机会进入缓存
"SELECT * FROM table WHERE param = '" + variable + "'"

您还应该将模式名称添加到查询中的表名(例如dbo.table)。否则,如果计划由不同的登录执行,则不会重复使用该计划。

答案 1 :(得分:0)

只要不动态地进行其他连接来检查可能重要的参数的值,并且唯一的动态部分是WHERE子句,这也可以是具有所有可能参数的静态查询。所以你有以下几种情况:

如果你想检查可以是所有东西的值(负/空/零/正/空字符串/等),需要使用辅助参数,例如@ signifficant_param1,以及@的原始值。参数1。

[...]
WHERE 
    (@signifficant_param1=0 or (@param1 is null and field1 is null) or @param1=field1) 
    AND (@signifficant_param2=0 or (@param2 is null and field2 is null) or @param2=field2)
    //etc
[...]

这是我能想象的最普遍的条款。 基本上它会验证@signifficant_param值。如果应该考虑该参数,则它将为1,条件的第一部分将为假,并且将发生第二部分(参数的验证)。在第二阶段,如果@param为空,那么您正在查找field的所有空值,并且您无法将null与null进行比较,因为它们不相等。然后进行常规非空值匹配的验证。

另一方面,如果field中的值不能为空,或者不能为负值,则不需要@signifficant_param,因为您可以制定规则,例如,如果@param为null,则此值不具有显着性(在前一种情况下,您必须搜索所有空值),您可以使用以下内容:

[...]
WHERE
    field1=case when @param1 is null then field1 else @param1 end --first way with case statement
    and (@param2 is null or field2=@param2) --second way with boolean logic
[...]

答案 2 :(得分:0)

动态查询本身没有任何问题。但是你打算这样做的方式是可怕的。它有点暗示你的参数将成为@Filter的一部分,它只是要求SQL注入攻击。这也意味着您的查询计划不太可能被重用,由于过多的查询重新编译,这可能导致高CPU和低吞吐量。

您需要确保生成的动态SQL已正确参数化。您还需要确保在使用ADO.NET代码(或您可能使用的任何数据访问技术)访问它时,使用SqlParameter(或等效的)对象。