#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