Динамический SQL - EXEC (@SQL) против EXEC SP_EXECUTESQL (@SQL)


95

Каковы реальные плюсы и минусы выполнения динамической команды SQL в хранимой процедуре в SQL Server с использованием

EXEC (@SQL)

против

EXEC SP_EXECUTESQL @SQL

?

Ответы:


96

sp_executesqlс большей вероятностью будет способствовать повторному использованию плана запроса. При использовании sp_executesqlпараметры явно указываются в вызывающей сигнатуре. Эта отличная статья описывает этот процесс .

Часто цитируемый справочник по многим аспектам динамического SQL - это то, что Эрланд Соммарског должен прочитать: « Проклятие и благословение динамического SQL ».


21

Важность SP_EXECUTESQL заключается в том, что он позволяет создавать параметризованные запросы, что очень хорошо, если вы заботитесь о SQL-инъекции.


1
Я не думаю, что вы можете параметризовать динамический sql без него ??
DJ.

EXEC ('SELECT * FROM FOO WHERE ID =?', 123) заменит заполнитель параметра "?" со значением 123, а затем выполните запрос, вернув результат для SELECT * FROM FOO WHERE ID = 123
Питер Вон

1
К сожалению, этот синтаксис доступен только для связанных серверов.
Питер Вон

1
Абсолютно одна из главных причин использовать sp_executesql при динамическом построении запроса для предотвращения внедрения sql.
Стивен Роджерс

5

В статье Microsoft по использованию sp_executesql рекомендуется использовать sp_executesqlвместо executeоператора.

Поскольку эта хранимая процедура поддерживает подстановку параметров , процедура sp_executesql более универсальна, чем EXECUTE; и поскольку процедура sp_executesql генерирует планы выполнения, которые с большей вероятностью будут повторно использоваться SQL Server, процедура sp_executesql более эффективна, чем EXECUTE.

Итак, вывод: не используйте executeзаявление . Используйте sp_executesql.


7
Ваш вынос не всегда актуален. Бывают случаи, когда использование sp_executesql не дает бонуса за эффективность, но вы можете защитить свой код от атаки с использованием sql-инъекции. Иногда вы просто не можете использовать sp_executesql так, как вы можете использовать exec, поэтому ... кто-то сказал - нет серебряной пули. Согласен.
OzrenTkalcecKrznaric

Да, Microsoft должна положить его в качестве «более вероятно , чтобы быть эффективными». И, работая в отрасли несколько лет, я видел случаи, когда sp_executesqlих нельзя было использовать для замены execute. Возможно, мне следует выразить мысль, которую я пытаюсь подчеркнуть, как: «Используйте sp_executesqlвместо того, execute когда это возможно» .
Ган

2

В наши дни я бы всегда использовал sp_executesql, все, что на самом деле является оболочкой для EXEC, которая обрабатывает параметры и переменные.

Однако не забывайте о OPTION RECOMPILE при настройке запросов в очень больших базах данных, особенно если у вас есть данные, охватывающие более одной базы данных, и вы используете CONSTRAINT для ограничения сканирования индекса.

Если вы не используете OPTION RECOMPILE, SQL-сервер попытается создать план выполнения «один размер для всех» для вашего запроса и будет запускать полное сканирование индекса при каждом его запуске.

Это намного менее эффективно, чем поиск, и означает, что он потенциально сканирует целые индексы, которые ограничены диапазонами, которые вы даже не запрашиваете: @


-2
  1. Объявить переменную
  2. Задайте его своей командой и добавьте динамические части, например, используйте значения параметров sp (здесь @IsMonday и @IsTuesday - sp params)
  3. выполнить команду

    declare  @sql varchar (100)
    set @sql ='select * from #td1'
    
    if (@IsMonday+@IsTuesday !='')
    begin
    set @sql= @sql+' where PickupDay in ('''+@IsMonday+''','''+@IsTuesday+''' )'
    end
    exec( @sql)
    

15
Это открыто для внедрения SQL, если вы поместите, например, "a '; DROP DATABASE DATABASE_NAME; GO;';" в переменной @IsMonday
Эрик А. Брандстадмоен

склонен ли он к нарушению sql, если @IsMonday является int?
Викас Рана

@VikasRana @IsMonday не может быть intв динамическом SQL. Обратите внимание, что @sql объявлен как varcharornvarchar
Weihui Guo
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.