动态SQL查询中的串联问题

时间:2019-03-18 07:58:39

标签: sql sql-server tsql

我正在尝试将具有多个变量的字符串连接起来并执行。不幸的是,我面临的转换问题是:

  

将varchar值'Select @ 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 个答案:

答案 0 :(得分:2)

“简单”的答案是不要原始字符串值连接到动态语句中,并参数设置您的代码。这只是猜测的 位,比现在的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 :(得分:1)

您似乎想要:

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 ('')
                      )
';