Как избежать одинарной кавычки в динамическом SQL

У меня есть следующий запрос на SQL Server, некоторые значения хранятся в переменных, вычисленных ранее:

SET @Command = N'INSERT INTO Products (Id
                                ,Region
                                ,Name
                                ,Category
                                ,CreatedBy
                                ,CreatedOn
                                ,) SELECT ' + @Id + ',
                                            Region, 
                                            ''' + @ProductName + ''', 
                                            Category,
                                            CreatedBy,
                                            CreatedOn FROM ' + @ProductTable + ' 
                                                WITH (NOLOCK) WHERE Id IS NOT NULL';

    EXEC(@Command)

Он работает нормально, за исключением случаев, когда значение @ProductName содержит кавычки (например, Продукт Джима), и в этом случае я получаю следующую ошибку:

Незакрытая кавычка после строки символов

Есть ли способ обрабатывать одинарные кавычки в переменной в таком динамическом запросе, где одно из выбранных вставляемых значений (в данном случае @ProductName) является непосредственно значением, которое должно быть вставлено вместо фактического имени столбца в исходной таблице, чей значение нужно получить для вставки?


person Cranialsurge    schedule 01.03.2017    source источник
comment
Обязательно ли здесь делать динамический sql?   -  person Augwa    schedule 01.03.2017
comment
Какую базу данных вы используете?   -  person Utsav    schedule 01.03.2017
comment
@Utsav: SQL-сервер. Обновил и основной пост.   -  person Cranialsurge    schedule 01.03.2017
comment
@Augwa: переменные извлекаются из другого блока в том же запросе ранее. Этот конкретный фрагмент получает эти значения и в настоящее время является динамическим. Вы имели в виду альтернативу?   -  person Cranialsurge    schedule 01.03.2017


Ответы (1)


Лучше всего использовать sp_executesql вместо EXEC и использовать правильный параметр для значение @ProductName.

Остальная часть запроса, которая не может быть параметризована (имя таблицы @ProductTable), останется динамической конкатенацией строк.

В этом случае вам не нужно ничего экранировать, и вы защищены от SQL-инъекций.

Что-то вроде этого:

SET @Command = 
    N'INSERT INTO Products
        (Id
        ,Region
        ,Name
        ,Category
        ,CreatedBy
        ,CreatedOn)
    SELECT
        @ParamId
        ,Region
        ,@ParamProductName
        ,Category
        ,CreatedBy
        ,CreatedOn
    FROM ' + @ProductTable + N' WITH (NOLOCK)
    WHERE ID IS NOT NULL'
    ;

EXEC sp_executesql
    @Command
    ,N'@ParamId int, @ParamProductName nvarchar(255)'
    ,@ParamId = @Id
    ,@ParamProductName = @ProductName
;
person Vladimir Baranov    schedule 01.03.2017
comment
Идеально, именно то, что мне было нужно! Спасибо @Владимир. - person Cranialsurge; 01.03.2017