将多种数据类型传递给动态 sql-values 而不是传递参数化查询

passing multiple datatypes into dynamic sql-values not passing in parameterized query

我在存储过程中有一个动态 SQL 查询,该查询有效并为我提供了正确的结果。但它花费的时间太长了——因为我必须将其作为 varchar 而不是 int 进行比较。我相信 SQL 服务器中的 @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;

这是比较- SELECT CIdentifier FROM #tempTable temp WITH(NOLOCK) 其中 temp.CIdentifier < '+@Id+'....

这比较为 CIdentifier =1122233 而不是 CIdentifier ='1122233' 因为动态 SQL 不允许我将它作为 int 传递。我不断收到 'cannot convert varchar to int error'

所以我使用了参数化查询 - 希望这能让我传递 int values.Here 是查询部分

        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 

这给了我不正确的结果,当我看到使用跟踪执行时 - 看到值没有传递到查询。如何获取查询以获取变量?

只需在第一个查询中将 WHERE ParentCId = '+ @Id + ' 更改为 WHERE ParentCId = '+ cast(@Id as varchar(16)) + '。问题是 SQL 服务器将 + 视为加法,当值是 numeric 类型时,或 date,如果不是,则将其视为连接。这是您从中得到错误的地方。但是,当您这样做时,它不会使 SQL 服务器将其作为字符串文字进行比较,因此您不必担心这一点。如果你在末尾使用 PRINT (@Query) 而不是 EXEC (@Query)

就可以看到这一点

请注意,这需要在您拥有任何 NUMERIC 数据类型的其他位置进行更改,例如 SELECT 部分,SELECT '+ cast(@Id as varchar(16)) +'

此外,您的代码没有显示 @Id 值的来源,因此请注意此处的 SQL 注入。