Недопустимое имя столбца при использовании динамического SQL

#sql-server #tsql #dynamic-sql

Вопрос:

Я хочу выполнить следующую динамическую инструкцию T-SQL:

 CREATE PROCEDURE MergeTable @TableName NVARCHAR(max) 
AS BEGIN
DECLARE @MergeStatement NVARCHAR(max)
SET @MergeStatement = 'SELECT Query FROM dbo.QueryMergeDWH WHERE SourceTableName = '   @TableName
EXEC sp_executesql @MergeStatement
END

EXEC MergeTable @TableName = 'SGPREINVOICE'
 

Однако это приводит меня к следующей ошибке:

Msg 207, Уровень 16, Состояние 1, Строка 17 Недопустимое имя столбца «SGPREINVOICE».

Это действительно работает:

 SELECT 'SELECT Query FROM dbo.QueryMergeDWH WHERE SourceTableName = '   'SGPREINVOICE'
 

Что я здесь делаю не так?

Комментарии:

1. не цитируя его в динамическом случае.

2. ПРЕДУПРЕЖДЕНИЕ : Это огромная проблема с инъекциями. Вы даете злоумышленнику возможность ввести 2 миллиарда байт (1 миллиард символов) любого SQL, который он хочет. Если это выполняется под LOGIN / USER с достаточно высокими разрешениями, они могут буквально делать все , что захотят, с минимальными усилиями. НИКОГДА не вводите незапланированные строки в динамический оператор и не используйте MAX их для имени объекта. Для имен объектов существует определенный тип данных: sysname .

3. Вот пример параметризованного запроса, который решит вашу проблему и улучшит безопасность: SET @MergeStatement = N'SELECT Query FROM dbo.QueryMergeDWH WHERE SourceTableName = @TableName';EXEC sp_executesql @MergeStatement, N'@TableName nvarchar(523)', @TableName = @TableName; ;

Ответ №1:

Вам необходимо параметризовать динамический запрос. Таким образом, вы проходите @TableName весь путь до конца

 CREATE PROCEDURE MergeTable @TableName NVARCHAR(max) 
AS

DECLARE @MergeStatement NVARCHAR(max);

SET @MergeStatement = '
SELECT Query
FROM dbo.QueryMergeDWH
WHERE SourceTableName = @TableName;
';

EXEC sp_executesql
    @MergeStatement,
    N'@TableName nvarchar(max)',
    @TableName = @TableName;

GO
 

Но неясно, что в этом динамичного, вы могли бы с таким же успехом сделать

 
CREATE PROCEDURE MergeTable @TableName NVARCHAR(max) 
AS

SELECT Query
FROM dbo.QueryMergeDWH
WHERE SourceTableName = @TableName;

GO