Важный аспект, который следует помнить о внедрении SQL, заключается в том, что, если это вообще возможно, вы никогда не должны вставлять предоставленные пользователем значения непосредственно в ваш SQL . Это не означает, что вы не можете использовать динамический sql (хотя это определенно упрощает ситуацию, если вы не ), но иногда это становится более опасным.
В вашем конкретном примере вы можете сохранить параметризацию всего, кроме @field_name
. К сожалению, это должно быть встроено непосредственно в SQL; все остальное можно снова передать в качестве параметра, поэтому не нужно беспокоиться об их содержимом.
Самое безопасное, что вы можете сделать в этом конкретном примере, это:
if(exists (select 1 from INFORMATION_SCHEMA.Columns where TABLE_NAME = 'Table' and TABLE_SCHEMA = 'dbo' and COLUMN_NAME = @fieldName))
begin
DECLARE @sql nvarchar(1000)
SET @sql = 'UPDATE dbo.TABLE '+
'SET ' + QUOTENAME(@field_name) + '=@value ' +
'WHERE company_id=@company_id AND '+
'id=@id'
exec sp_executesql @sql,N'@id bigint, @company_id uniqueidentifier, @value nvarchar(50)',@id,@company_id,@value
end
Это делает две вещи:
- Он проверяет, что в таблице действительно есть столбец с таким именем. Если бы пользователь вставил в поле любые другие операторы SQL, эта проверка завершилась бы неудачно и оператор не был бы выполнен. Вы также можете позвонить
raiseerror
, чтобы сообщить об ошибке, но я оставлю это упражнение на ваше усмотрение.
- Оно заключает имя поля в квадратные скобки, чтобы имена полей, содержащие пробелы или зарезервированные слова, не нарушали оператор. Это может не быть проблемой для вас, но всегда полезно, если вы сами генерируете SQL.