Недостатки динамического запроса в Sqlserver 2005? - PullRequest
2 голосов
/ 11 мая 2010

Я использовал много динамических запросов в моей базе данных для процедур, потому что мой фильтр не является фиксированным, поэтому я принял @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 ]

2 голосов
/ 11 мая 2010

Для производительности вопрос только в том, может ли база данных повторно использовать существующий план или нет.

Проще говоря, это можно увидеть, поскольку база данных кэширует план запроса с оператором sql в качестве ключа. Как только вы измените оператор SQL, он не будет в кеше, и новый план должен быть сгенерирован.

Таким образом, генерация динамических операторов, таких как

"SELECT * FROM table WHERE param = @paramvalue"

имеет больше шансов быть в кеше, чем

"SELECT * FROM table WHERE param = '" + variable + "'"

Вы также должны добавить имя схемы к именам таблиц в запросе (например, dbo.table). В противном случае план не будет использоваться повторно, если он выполняется разными логинами.

0 голосов
/ 11 мая 2010

По сути, в динамических запросах нет ничего плохого. Но то, как вы собираетесь это сделать, страшно. Это как бы подразумевает, что ваши параметры будут частью @Filter, который просто запрашивает атаку SQL-инъекцией. Это также означает, что ваш план запроса вряд ли будет использоваться повторно, что может привести к высокой загрузке ЦП и низкой пропускной способности из-за чрезмерной перекомпиляции запроса.

Вы должны убедиться, что динамический SQL, который вы генерируете, правильно параметризован. Вам также необходимо убедиться, что при доступе к нему с помощью кода ADO.NET (или любой другой технологии доступа к данным, которую вы используете) вы используете объект SqlParameter (или эквивалентный).

0 голосов
/ 11 мая 2010

Поскольку никакие другие объединения не должны выполняться динамически для проверки значения параметра, который может иметь значение, и единственной динамической частью является предложение WHERE, это также может быть статический запрос, который имеет все возможные параметры. Итак, у вас есть следующие сценарии:

Если вы хотите проверить значения, которые могут быть любыми (отрицательные / нули / нули / положительные / пустые строки / и т. Д.), Необходимо использовать вспомогательный параметр, например @ signifficant_param1, вместе с исходным значением @ param1.

[...]
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 и не можете сравнить ноль с нулем, потому что они не равны. Затем происходит проверка правильности совпадения ненулевых значений.

Если, с другой стороны, значения в field не могут быть нулевыми или не могут быть отрицательными, вам не нужен @signifficant_param, потому что вы можете создать правило, например, если @param равно нулю, тогда это значение не имеет значения (в предыдущем случае вам пришлось бы искать все нулевые значения), вы можете использовать следующее:

[...]
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
[...]
...