将多种数据类型传递给动态 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 注入。
我在存储过程中有一个动态 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 注入。