Динамічний 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 без нього ??
діджей.

EXEC ('SELECT * FOO WHERE ID =?', 123) замінить заповнення параметра "?" зі значенням 123, а потім виконати запит, повертаючи результат для SELECT * FOO FERE WHERE ID = 123
Peter Wone

1
На жаль, цей синтаксис доступний лише для пов'язаних серверів.
Пітер Вун

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

5

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

Оскільки ця збережена процедура підтримує підстановку параметрів , sp_executesql є більш універсальним, ніж EXECUTE; і оскільки sp_executesql генерує плани виконання, які, швидше за все, будуть використані SQL Server, sp_executesql є більш ефективним, ніж EXECUTE.

Отже, take away: Не використовуйте 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 - це пара-парами)
  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 оголошено як varcharабоnvarchar
Weihui Guo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.