sp_executesql 是否支持一个参数中的多个值和 return 多个记录?

Does sp_executesql support multiple values in one parameter and return multiple records?

我创建了一个如下所示的存储过程,但它只返回一行而不是 3 行:

CREATE PROCEDURE [dbo].[tempsp] 
    (@RecycleIds NVARCHAR(MAX) = NULL)  
AS  
BEGIN  
    DECLARE @Err INT  
    DECLARE @WhereClause NVARCHAR(MAX)  
    DECLARE @SQLText1 NVARCHAR(MAX)  
    DECLARE @SQLText NVARCHAR(MAX)
  
    SET @SQLText1 = 'SELECT FROM dbo.SKU '  
  
    IF @RecycledSkuIds IS NOT NULL  
    BEGIN      
        SET @SQLText = 'SELECT FROM dbo.SKU WHERE SKU.SkuId IN (@RecycleIds)'

        EXEC sp_executesql @SQLText, N'@RecycleSkuIds nvarchar', @RecycleIds 
    END   
    ELSE  
    BEGIN  
        EXEC(@SQLText1)
    END           
  
    SET @Err = @@ERROR  
    RETURN @Err  
END  
-------end of stored procedure--------


EXEC tempsp @RecycleIds = '5,6,7'

在 运行 这个 SQL 语句之后,它只有 returns 一行而不是 3 行,id 为 5、6、7。

谁能告诉我我做错了什么? 我想使用 sp_executesql,这样它就可以安全地防止 sql 定义了强类型的注入。

您不能使用 IN。或者,更准确地说,您有一个字符串,但您将它与列表混淆了。一种方法是改为使用 LIKE:

SET @SQLText = '
SELECT *
FROM dbo.SKU
WHERE CONCAT('','', @RecycleIds, '','') LIKE CONCAT(''%,'', SKU.SkuId, '',%'')
';

使用 table 类型参数,具有强类型列:

CREATE TYPE dbo.IDs AS table (ID int);
GO

CREATE PROCEDURE [dbo].[tempsp] @RecycleIds dbo.IDs READONLY AS
BEGIN

    IF EXISTS (SELECT 1 FROM @RecycleIds)
        SELECT * --Replace with needed columns
        FROM dbo.SKU S
        --Using EXISTS in case someone silly puts in the same ID twice.
        WHERE EXISTS (SELECT 1
                      FROM @RecycleIds R
                      WHERE R.ID = S.SkuID);
    ELSE
        SELECT * --Replace with needed columns
        FROM dbo.SKU S
END;
GO

然后你可以这样执行:

EXEC dbo.tempsp; --All Rows
GO
DECLARE @RecycleIds dbo.IDs;
INSERT INTO @RecycleIds
VALUES(1),(40),(182);

EXEC dbo.tempsp @RecycleIds;

我试图检索 ID 在 IN 子句中匹配的行。

SET @INClauseIds='''' + replace(@Ids, ',', ''',''') + ''''  

上面的语句会将 ID 的 ='1,2,3' 转换为 '1','2','3' 我可以直接将其放在 IN 子句中。

SET @SQLText1 ='EXEC(''SELECT  Name,SEOFriendlyName FROM SKU Where Id IN ( ''+ @Ids+'' ) )'             

 EXEC sp_executesql @SQLText1 ,N'@INClauseIds nvarchar(max)',@Ids=@INClauseIds 

如果您想避免使用 Temp Table,这会增加额外的计算时间。您可以使用上述策略来检索 n 条记录。与 sp_executesql 强耦合并且没有任何 sql 注入是安全的。