Подтвердить что ты не робот

Сохраненная процедура EXEC vs sp_executesql разница?

Я написал две хранимые процедуры с sp_executesql, а у других нет sp_executesql оба выполняются правильно одинаковые результаты, я не понял, в чем разница между

EXEC (@SQL) vs EXEC sp_executesql @SQL, N '@eStatus varchar (12)', @eStatus = @Status

и как EXEC (@SQL) подвержен SQL-инъекциям и sp_executesql @SQL...... не?

Ниже хранимой процедуры без sp_executesql

ALTER proc USP_GetEmpByStatus
(
@Status varchar(12)
)
AS
BEGIN
DECLARE @TableName AS sysname = 'Employee'
Declare @Columns as sysname = '*'
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + @TableName + ' where Status=' + char(39) + @Status + char(39)
print (@SQL)
EXEC (@SQL)
END

EXEC USP_GetEmpByStatus 'Active'

Ниже хранимой процедуры с sp_executesql

create proc USP_GetEmpByStatusWithSpExcute
(
@Status varchar(12)
)
AS
BEGIN
DECLARE @TableName AS sysname = 'JProCo.dbo.Employee'
Declare @Columns as sysname = '*'
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + @TableName + ' where Status=' + char(39) + @Status + char(39)
print @SQL
exec sp_executesql @SQL, N'@eStatus varchar(12)', @eStatus = @Status
END

EXEC USP_GetEmpByStatusWithSpExcute 'Active'
4b9b3361

Ответ 1

Вероятно, ваш SQL sp_executesql должен быть:

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
            @TableName + ' where [email protected]'

Это позволит вам вызвать sp_executesql с @eStatus в качестве параметра, а не встраивать его в SQL. Это даст преимущество в том, что @eStatus может содержать любые символы, и он будет автоматически автоматически экранироваться базой данных, если это необходимо для обеспечения безопасности.

Сравните это с SQL, необходимым для EXEC;

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
            @TableName + ' where Status=' + char(39) + @Status + char(39)

... где a char (39), встроенный в @Status, сделает ваш SQL недействительным и, возможно, создаст возможность SQL-инъекции. Например, если для параметра @Status установлено значение O'Reilly, результатом будет SQL:

select acol,bcol,ccol FROM myTable WHERE Status='O'Reilly'

Ответ 2

Помимо использования, существуют некоторые важные отличия:

  • sp_executesql позволяет параметризировать операторы Поэтому он более безопасен, чем EXEC с точки зрения SQL-инъекции

  • sp_executesql может использовать кэшированные планы запросов. Строка TSQL создается только один раз, после этого каждый раз, когда тот же запрос вызывается с помощью sp_executesql, SQL Server извлекает план запроса из кеша и повторно использует его

  • Таблицы Temp, созданные в EXEC, не могут использовать механизм кэширования таблицы temp

Ответ 3

С sp_executesql вам не нужно строить свой запрос таким образом. Вы можете объявить это следующим образом:

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
@TableName + ' where [email protected]'

Таким образом, если ваше значение @Status пришло от пользователя, вы можете использовать @eStatus и не беспокоиться об экранировании '. sp_executesql дает возможность помещать переменные в ваш запрос в строковой форме, а не использовать конкатенацию. Поэтому вам не о чем беспокоиться.

Переменные столбца и таблицы все те же, но менее вероятно, что они будут непосредственно от пользователя.

Ответ 4

С Exec У вас не может быть владелец места в строке оператора T-Sql.

sp_executesql дает вам преимущество наличия держателя места и передачи фактического значения в время выполнения