我在存储过程中有一个动态SQL查询,该查询可以工作并给出正确的结果。但这花了太长时间,因为我必须将其比较为varchar而不是int。我相信SQL Server中的@query变量要求该语句为unicode。 这是动态sql部分
ALTER PROCEDURE [dbo].[sp_GetRows]( @Id varchar(64))
AS
BEGIN
DECLARE @Query nvarchar(4000),
@Comp varchar(256)
SELECT @Comp
= STUFF((
SELECT DISTINCT ',' + char(39)+
tci.Component +char(39)
FROM TCI tci WITH(NOLOCK)
JOIN CDetail cd WITH(NOLOCK)
ON tci.ParentCId = cd.CIdentifier
WHERE tci.ParentCId = @Id
AND cd.ParentBranch IS NULL
FOR XML PATH('')),1,1,'')
SET @Query
= 'WITH CTE AS
(
SELECT '+@Id+' as ParentCId, CIdentifier as ChildCId,
a.Comp as Comp
from dbo.CD cd WITH(NOLOCK)
INNER JOIN
(SELECT DISTINCT ChildCId,Comp
FROM TCI tc WITH(NOLOCK)
WHERE ParentCId = '+ @Id + '
) a
ON cd.CIdentifier= a.ChildCId
);
EXEC (@Query)
END;
这是比较- 从#tempTable中选择SELECT标识符TEMP WITH(NOLOCK) WHERE temp.CIdentifier <'+ @ Id +'....
这与CIdentifier = 1122233而不是CIdentifier ='1122233'相比,因为动态SQL不允许我将其作为整数传递。我不断收到“无法将varchar转换为int错误”
因此,我使用了参数化查询-希望能够使我传递int值。这是查询部分
SET @Query
= N';WITH CTE AS
(
......
(SELECT DISTINCT ChildCId,Comp
FROM TCI tc WITH(NOLOCK)
WHERE ParentCId = @Id
AND ChildCId + tc.Comp
NOT IN
(SELECT ChildId + Comp FROM dbo.TCI WITH(NOLOCK)
WHERE ParentId IN (SELECT CIdentifier FROM #tempTable WITH(NOLOCK)
WHERE temp.CIdentifier < @Idn
AND Comp IN ( @Comp))
)
)
)a
ON cd.CIdentifier= a.ChildId
)
SELECT * FROM CTE;'
EXEC sp_executeSQL @Query,'@Id VARCHAR(64),@Idn INT,@comp VARCHAR(256)',@Id=@Id,@Idn=@Idn,@comp =@comp
这给了我错误的结果,并且当我看到使用跟踪的执行时-看到没有将值传递到查询中。如何获取查询以获取变量?
答案 0 :(得分:1)
只需在第一个查询中将WHERE ParentCId = '+ @Id + '
更改为WHERE ParentCId = '+ cast(@Id as varchar(16)) + '
。问题在于,当值是+
类型或numeric
类型时,SQL Server将date
视为加法,否则将其串联。这是您得到错误的地方。但是,执行此操作时,它不会使SQL Server将其与字符串文字进行比较,因此您不必为此担心。如果您在末尾使用PRINT (@Query)
而不是EXEC (@Query)
请注意,需要在您拥有任何NUMERIC
数据类型的其他位置进行更改,例如在SELECT
部分SELECT '+ cast(@Id as varchar(16)) +'
此外,您的代码不会显示@Id
值的来源,因此请谨慎使用SQL注入。