SQL dinamico - EXEC (@SQL) contro EXEC SP_EXECUTESQL (@SQL)


95

Quali sono i pro ei contro del mondo reale nell'esecuzione di un comando SQL dinamico in una stored procedure in SQL Server utilizzando

EXEC (@SQL)

contro

EXEC SP_EXECUTESQL @SQL

?

Risposte:


96

sp_executesqlè più probabile che promuova il riutilizzo del piano di query. Quando si utilizza sp_executesql, i parametri vengono identificati esplicitamente nella firma chiamante. Questo eccellente articolo descrive questo processo .

Il riferimento spesso citato per molti aspetti dello sql dinamico è che Erland Sommarskog deve leggere: " The Curse and Blessings of Dynamic SQL ".


21

La cosa importante di SP_EXECUTESQL è che ti consente di creare query parametrizzate, il che è molto buono se ti interessa l'iniezione SQL.


1
Non penso che tu possa parametizzare uno sql dinamico senza di esso ??
DJ.

EXEC ('SELECT * FROM FOO WHERE ID =?', 123) sostituirà il segnaposto del parametro "?" con il valore 123 e quindi eseguire la query, restituendo un risultato per SELECT * FROM FOO WHERE ID = 123
Peter Wone

1
Spiacenti, questa sintassi è disponibile solo per i server collegati.
Peter ha vinto il

1
Assolutamente uno dei motivi principali per utilizzare sp_executesql se si crea la query in modo dinamico per impedire l'iniezione sql.
Steven Rogers

5

L' articolo di Microsoft Using sp_executesql consiglia di utilizzare sp_executesqlinvece di executestatement.

Poiché questa stored procedure supporta la sostituzione dei parametri , sp_executesql è più versatile di EXECUTE; e poiché sp_executesql genera piani di esecuzione che hanno maggiori probabilità di essere riutilizzati da SQL Server, sp_executesql è più efficiente di EXECUTE.

Quindi, il take away: non usare la executedichiarazione . Usa sp_executesql.


7
Il tuo asporto non è sempre valido. Ci sono occasioni in cui non ci sono bonus di efficienza utilizzando sp_executesql, ma puoi proteggere il tuo codice da attacchi sql injection. A volte non puoi usare sp_executesql nel modo in cui puoi usare exec, quindi ... qualcuno ha detto: non esiste un proiettile d'argento. Sono d'accordo.
OzrenTkalcecKrznaric

Sì, Microsoft avrebbe dovuto definirlo "con maggiori probabilità di essere efficiente". Ed essendo nel settore da alcuni anni, ho visto casi in cui sp_executesqlnon può essere utilizzato per sostituire execute. Forse dovrei mettere il punto che sto cercando di sottolineare come: usa sp_executesqlinvece di execute quando possibile .
Gan

2

In questi giorni userei sempre sp_executesql, tutto ciò che è veramente è un wrapper per EXEC che gestisce parametri e variabili.

Tuttavia, non dimenticare OPTION RECOMPILE quando si ottimizzano le query su database di grandi dimensioni, soprattutto quando i dati si estendono su più di un database e si utilizza un CONSTRAINT per limitare le scansioni dell'indice.

A meno che non si utilizzi OPTION RECOMPILE, il server SQL tenterà di creare un piano di esecuzione "taglia unica" per la query ed eseguirà una scansione completa dell'indice ogni volta che viene eseguita.

Questo è molto meno efficiente di una ricerca e significa che potenzialmente sta scansionando interi indici che sono vincolati a intervalli che non stai nemmeno interrogando: @


-2
  1. Dichiara la variabile
  2. Impostalo dal tuo comando e aggiungi parti dinamiche come usa i valori dei parametri di sp (qui @IsMonday e @IsTuesday sono parametri sp)
  3. eseguire il comando

    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
Questo è aperto a SQL injection, se metti ad esempio "a '; DROP DATABASE DATABASE_NAME; GO;';" nella variabile @IsMonday
Erik A. Brandstadmoen

è soggetto a iniezioni sql se @IsMonday è int?
Vikas Rana

@VikasRana @IsMonday non può essere intin SQL dinamico. Nota che @sql è dichiarato come varcharonvarchar
Weihui Guo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.