Проблема конкатенации в динамическом SQL-запросе - PullRequest
0 голосов
/ 18 марта 2019

Я пытаюсь объединить строку с несколькими переменными и перейти к exec.К сожалению, я сталкиваюсь с проблемой преобразования:

Преобразование не удалось при преобразовании значения varchar 'Выберите @ ExistingIds = CBSE_IX_J из ## tempPivot, где EmployeeID =', в тип данных int.

Мой запрос:

SET @ExecColumn = concat('Select @ExistingIds= '+@TSectionName +' from ##tempPivot where EmployeeID='+CAST(@TUserID as INT),'')
PRINT @ExecColumn
EXEC (@ExecColumn)

Ответы [ 2 ]

2 голосов
/ 18 марта 2019

«Простой» ответ: не объединение необработанных строковых значений в динамическом выражении и параметризация вашего кода. Это бит догадок, однако гораздо безопаснее, чем дыра в SQL-инъекции, которая у вас есть прямо сейчас:

DECLARE @SQL nvarchar(MAX);
SET @SQL = N'SELECT @ExistingIDs = ' + QUOTENAME(@TSectionName) + NCHAR(13) + NCHAR(10)+
           N'FROM ##tempPivot' + NCHAR(13) + NCHAR(10) +
           N'WHERE EmployeeID = @TUserID;';
PRINT @SQL;
EXEC sp_executesql @SQL,
                   N'@TUserID int, @ExistingIds int OUTPUT', --guessed datatypes and that @ExistingIds is an OUTPUT
                   @TUserID = @TUserID,
                   @ExistingIds = ExistingIds OUTPUT;

Примечание: тот факт, что ваша переменная называется @ExistingIDs , подразумевает , что вы хотите сохранить несколько значений в этой переменной. @ExistingIDs является скалярным значением, оно будет содержать только скалярное (одиночное) значение. Если запрос выше возвращает несколько строк, будет возвращено только значение из последней строки. Например:

DECLARE @i int;
SELECT @i = I
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9))V(I)
ORDER BY I;
SELECT @i;

Обратите внимание, что @i имеет значение 9, а не '1,2,3,...,9'.

1 голос
/ 18 марта 2019

Казалось бы, вы хотите:

DECLARE @SQL nvarchar(MAX);
DECALRE @ExistingIds NVARCHAR(MAX);

SET @SQL = N'
SELECT @ExistingIDs = STRING_AGG(@TSectionName, '''')
FROM ##tempPivot
WHERE EmployeeID = @TUserID
';

-- Cannot have identifiers as parameters, so use `REPLACE()`
SET @SQL = REPLACE(@SQL, '@TSectionName', QUOTENAME(@TSectionName);

EXEC sp_executesql @SQL,
                   N'@TUserID int, @ExistingIds NVARCHAR(MAX) OUTPUT', --guessed datatypes and that @ExistingIds is an OUTPUT
                   @TUserID=@TUserID,
                   @ExistingIds=@ExistingIds OUTPUT;

В более старых версиях SQL Server вам нужен другой подход для объединения строк. Например

SET @SQL = N'
SELECT @ExistingIDs = (SELECT @TSectionName
                       FROM ##tempPivot
                       WHERE EmployeeID = @TUserID
                       FOR XML PATH ('')
                      )
';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...