Автор: Konstantin Kosinsky
Сегодня потребовалось передать SQL параметр в динамический SQL запрос именно как параметр, а не путем конкатенации строк. Причина довольно простая, значение параметра приходит от клиента, и если я сделаю конкатенацию, то сразу попаду в область SQL Injection, чего бы мне не хотелось.
Первая идея которая возникла — это воспользоваться выражением EXECUTE. Но проблема в том, что если EXECUTE использовать в контексте
EXECUTE usp_MyStoredProcedure @Param=@OtherParam, ...
, то есть, когда имя хранимой процедуры задано явно, передача параметров не вызывает вопросов.
Но если я хочу, динамический SQL:
EXECUTE (@query, @Param=@OtherParam,... )
, то конечно же получаю ошибку.
На такую же проблему натолкнулся наш коллега работая с динамическим SQL и полем ntext Как обработать тип ntext,image в T-SQL.
Но все-таки решение было найдено, и этим решением есть системная хранимая процедура sp_executesql, которая выглядит следующим образом:
sp_executesql @query, @parameters, @Param1=@OtherParam1,....
,где @query — динамически составленный запрос, @parameters — описание параметров передаваемых в запрос.
В результате у меня получилась следующая процедура:
CREATE PROCEDURE usp_UpdateFieldLogged @ID bigint, @User varchar(100), @Field varchar(100), @FieldType varchar(30), @Value nvarchar(200) – Поле, которому нельзя доверять AS /* Мой код логирования */ declare @query nvarchar(1000) set @query = 'UPDATE [MyTable] SET ' + @Field + ' = @Value WHERE ID=@ID '; EXECUTE sp_executesql @query, @Parameters = N'@ID bigint, @Value '+@FieldType ,@Value= @Value, @ID = @ID RETURN 0;