#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
Я пытаюсь объединить строку с несколькими переменными и перейти к exec. К сожалению, я сталкиваюсь с проблемой преобразования как:
Произошел сбой преобразования при преобразовании значения переменной ‘Select @ExistingIds= CBSE_IX_J from ##tempPivot where EmployeeID=’ в тип данных int.
Мой запрос :
SET @ExecColumn = concat('Select @ExistingIds= ' @TSectionName ' from ##tempPivot where EmployeeID=' CAST(@TUserID as INT),'')
PRINT @ExecColumn
EXEC (@ExecColumn)
Комментарии:
1.
CAST(@TUserID as INT)
=>CAST(@TUserID as VARCHAR(20)
. Кроме того, неясно, почемуCONCAT()
был использован в вашем фрагменте2. В чем смысл этого запроса? Нет причин использовать конкатенацию строк для @TUserID. Выполнение этого запроса также завершится неудачей, поскольку параметры и переменные должны быть определены в области, в которой они используются — в самом запросе
Ответ №1:
«Простой» ответ заключается в том, что не объединяйте необработанные строковые значения в свой динамический оператор и параметризуйте свой код. Однако это немного наугад, гораздо безопаснее, чем дыра в 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'
.
Ответ №2:
Казалось бы, вы хотите:
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 ('')
)
';