我在我的数据库中使用了很多动态查询程序,因为我的过滤器没有修复,所以我把@filter作为参数并传入了程序。
Declare @query as varchar(8000)
Declare @Filter as varchar(1000)
set @query = 'Select * from Person.Address where 1=1 and ' + @Filter
exec(@query)
就像我的过滤器包含表中的任何字段以进行比较。
这会影响我的表现吗? 有没有其他方法来实现这类事情
答案 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(或等效的)对象。