SQL dinámico: EXEC (@SQL) versus EXEC SP_EXECUTESQL (@SQL)


95

¿Cuáles son los pros y los contras del mundo real de ejecutar un comando SQL dinámico en un procedimiento almacenado en SQL Server usando

EXEC (@SQL)

versus

EXEC SP_EXECUTESQL @SQL

?

Respuestas:


96

sp_executesqles más probable que promueva la reutilización del plan de consultas. Cuando se usa sp_executesql, los parámetros se identifican explícitamente en la firma de llamada. Este excelente artículo describe este proceso .

La referencia frecuentemente citada para muchos aspectos del SQL dinámico es la lectura obligada de Erland Sommarskog: " La maldición y las bendiciones del SQL dinámico ".


21

Lo importante de SP_EXECUTESQL es que le permite crear consultas parametrizadas, lo cual es muy bueno si le importa la inyección SQL.


1
No creo que puedas parameteizar un sql dinámico sin él.
DJ.

EXEC ('SELECT * FROM FOO WHERE ID =?', 123) reemplazará el marcador de posición del parámetro "?" con el valor 123 y luego ejecute la consulta, devolviendo un resultado para SELECT * FROM FOO WHERE ID = 123
Peter Wone

1
Vaya, esa sintaxis solo está disponible para servidores vinculados.
Peter Wone

1
Absolutamente una de las razones más importantes para usar sp_executesql si se crea la consulta de forma dinámica para evitar la inyección de SQL.
Steven Rogers

5

El artículo de Microsoft Using sp_executesql recomienda usar en sp_executesqllugar de una executedeclaración.

Dado que este procedimiento almacenado admite la sustitución de parámetros , sp_executesql es más versátil que EXECUTE; y debido a que sp_executesql genera planes de ejecución que es más probable que sean reutilizados por SQL Server, sp_executesql es más eficiente que EXECUTE.

Entonces, para llevar: No use executedeclaración . Utilice sp_executesql.


7
Su comida para llevar no se mantiene siempre. Hay ocasiones en las que no hay una bonificación de eficiencia al usar sp_executesql, pero puede proteger su código del ataque de inyección SQL. A veces, simplemente no puede usar sp_executesql de la misma manera que puede usar exec, así que ... alguien dijo: no hay una solución milagrosa. Estoy de acuerdo.
OzrenTkalcecKrznaric

Sí, Microsoft debería haberlo dicho como "más probable que sea eficiente". Y al estar en la industria durante algunos años, he visto casos en los sp_executesqlque no se puede usar para reemplazar execute. Quizás debería poner el punto que estoy tratando de enfatizar como: Úselo en sp_executesqllugar de execute siempre que sea posible .
Gan,

2

Siempre usaría sp_executesql en estos días, todo lo que realmente es es un contenedor para EXEC que maneja parámetros y variables.

Sin embargo, no se olvide de OPTION RECOMPILE cuando ajuste consultas en bases de datos muy grandes, especialmente cuando tenga datos distribuidos en más de una base de datos y utilice una RESTRICCIÓN para limitar los análisis de índices.

A menos que use OPTION RECOMPILE, el servidor SQL intentará crear un plan de ejecución de "talla única" para su consulta, y ejecutará un escaneo de índice completo cada vez que se ejecute.

Esto es mucho menos eficiente que una búsqueda, y significa que potencialmente está escaneando índices completos que están restringidos a rangos que ni siquiera está consultando: @


-2
  1. Declarar la variable
  2. Configúrelo con su comando y agregue partes dinámicas como usar valores de parámetro de sp (aquí @IsMonday y @IsTuesday son sp params)
  3. ejecutar el 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
Esto está abierto a la inyección SQL, si pones, por ejemplo, "a '; DROP DATABASE DATABASE_NAME; GO;';" en la variable @IsMonday
Erik A. Brandstadmoen

¿Es propenso a una injuction sql si @IsMonday es int?
Vikas Rana

@VikasRana @IsMonday no puede estar inten SQL dinámico. Tenga en cuenta que @sql se declara como varcharonvarchar
Weihui Guo
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.