Dynamiczny SQL - EXEC (@SQL) a EXEC SP_EXECUTESQL (@SQL)

95

Jakie są rzeczywiste wady i zalety wykonywania dynamicznego polecenia SQL w procedurze składowanej w programie SQL Server przy użyciu

EXEC (@SQL)

przeciw

EXEC SP_EXECUTESQL @SQL

?

Ash Machine
źródło

Odpowiedzi:

96

sp_executesqljest bardziej prawdopodobne, że będzie promować ponowne wykorzystanie planu zapytań. Podczas używania sp_executesqlparametry są wyraźnie identyfikowane w sygnaturze wywołania. Ten wspaniały artykuł opisuje ten proces .

Często cytowanym odniesieniem dla wielu aspektów dynamicznego sql jest książka Erlanda Sommarskoga, którą trzeba przeczytać: „ Klątwa i błogosławieństwa dynamicznego SQL ”.

Mitch Wheat
źródło
21

Dużą zaletą SP_EXECUTESQL jest to, że pozwala tworzyć sparametryzowane zapytania, co jest bardzo dobre, jeśli zależy Ci na wstrzykiwaniu SQL.

DJ.
źródło
1
Nie sądzę, że można bez niego sparametryzować dynamiczny sql?
DJ.
EXEC ('SELECT * FROM FOO WHERE ID =?', 123) zastąpi symbol zastępczy parametru „?” z wartością 123, a następnie wykonaj zapytanie, zwracając wynik dla SELECT * FROM FOO WHERE ID = 123
Peter Wone
1
Ups, ta składnia jest dostępna tylko dla połączonych serwerów.
Peter wygrał
1
Absolutnie jeden z największych powodów, dla których warto używać sp_executesql podczas dynamicznego budowania zapytania, aby zapobiec iniekcji sql.
Steven Rogers
5

Artykuł Microsoftu Using sp_executesql zaleca używanie sp_executesqlzamiast executeinstrukcji.

Ponieważ ta procedura składowana obsługuje podstawianie parametrów , sp_executesql jest bardziej wszechstronna niż EXECUTE; a ponieważ sp_executesql generuje plany wykonania, które z większym prawdopodobieństwem zostaną ponownie wykorzystane przez SQL Server, sp_executesql jest bardziej wydajne niż EXECUTE.

A więc na wynos: nie używaj executeinstrukcji . Użyj sp_executesql.

Gan
źródło
7
Twoje dania na wynos nie zawsze są ważne. Są sytuacje, w których nie ma premii za wydajność przy użyciu sp_executesql, ale możesz chronić swój kod przed atakiem sql injection. Czasami po prostu nie możesz użyć sp_executesql tak, jak używasz exec, więc ... ktoś powiedział - nie ma srebrnej kuli. Zgadzam się.
OzrenTkalcecKrznaric
Tak, Microsoft powinien był to określić jako „bardziej prawdopodobne, że będzie skuteczny”. Będąc w branży od kilku lat, widziałem przypadki, w których sp_executesqlnie można ich zastąpić execute. Być może powinienem ująć to, co staram się podkreślić, jako: Używaj sp_executesqlzamiast tego, execute kiedy to możliwe .
Gan,
2

W dzisiejszych czasach zawsze używałbym sp_executesql, wszystko to naprawdę jest opakowaniem dla EXEC, które obsługuje parametry i zmienne.

Jednak nie zapomnij o OPCJI RECOMPILE podczas strojenia zapytań w bardzo dużych bazach danych, zwłaszcza gdy masz dane rozłożone na więcej niż jedną bazę danych i używasz OGRANICZENIA w celu ograniczenia skanowania indeksów.

O ile nie użyjesz OPCJI RECOMPILE, serwer SQL podejmie próbę utworzenia planu wykonania zapytania „jeden rozmiar dla wszystkich” i będzie przeprowadzał pełne skanowanie indeksu przy każdym uruchomieniu.

Jest to znacznie mniej wydajne niż wyszukiwanie i oznacza, że ​​potencjalnie skanuje całe indeksy, które są ograniczone do zakresów, których nawet nie pytasz: @

Ten98
źródło
-2
  1. Zadeklaruj zmienną
  2. Ustaw go za pomocą polecenia i dodaj dynamiczne części, takie jak użyj wartości parametrów sp (tutaj @IsMonday i @IsTuesday są parametrami sp)
  3. wykonać polecenie

    declare  @sql varchar (100)
    set @sql ='select * from #td1'
    
    if (@IsMonday+@IsTuesday !='')
    begin
    set @sql= @sql+' where PickupDay in ('''+@IsMonday+''','''+@IsTuesday+''' )'
    end
    exec( @sql)
    
Sara
źródło
15
To jest otwarte na wstrzyknięcie SQL, jeśli umieścisz np. "A '; DROP DATABASE DATABASE_NAME; GO;';" w zmiennej @IsMonday
Erik A. Brandstadmoen
czy jest podatny na uszkodzenie sql, jeśli @IsMonday jest int?
Vikas Rana
@VikasRana @IsMonday nie może być intw dynamicznym języku SQL. Zauważ, że @sql jest zadeklarowane jako varcharlubnvarchar
Weihui Guo