使用存储过程和 table 变量的动态 sql 查询

Dynamic sql query with stored procedure and table variable

我想动态调用存储过程,因为我的过程名称存储在某个地方,我还需要将该过程的结果存储到 table 变量中。因此,我不得不编写以下 sql 代码,

在下面的代码中 @tblEmailIds 是 table 变量,我想将 SP 的结果存储在其中 @tempEmailSource 是过程的名称 @tempRecipientsIdsCSV 是我的 SP 接受的第一个参数 @ObjectMasterId 是 SP 接受的第二个参数(可选)

DECLARE @tempTypeName NVARCHAR(100), 
            @tempTypeId INT,
            @tempEmailSource NVARCHAR(100),
            @tempRecipientsIdsCSV NVARCHAR(MAX),
            @tempIsObjectSpecific BIT,
            @sqlQuery NVARCHAR(MAX) = 'INSERT INTO @tblEmailIds '
SELECT TOP 1 @tempTypeName = NAME, 
@tempTypeId = Id,         
@tempEmailSource = EmailListSourceName 
FROM @tbleRecipientsTypes WHERE IsEmailIdsFetched = 0

    SELECT @tempRecipientsIdsCSV = SUBSTRING(
    (SELECT ',' + CAST(RT.EmailRecipientId AS NVARCHAR(50))
    FROM @tbleRecipientsTypes RT WHERE RT.Id = @tempTypeId
    ORDER BY RT.EmailRecipientId
    FOR XML PATH('')),2,200000)

    SELECT @tempRecipientsIdsCSV


    SET @sqlQuery = @sqlQuery + 'EXEC ' + @tempEmailSource +' ' +''''  +    @tempRecipientsIdsCSV +''''
    IF (@tempIsObjectSpecific = 1)
    BEGIN
        SET @sqlQuery = @sqlQuery + ' ' + @ObjectMasterId
    END

    PRINT @SQLQUERY

    EXECUTE SP_EXECUTESQL 
    @SqlQuery,'@IdsCSV NVARCHAR(MAX) OUTPUT,  
    @ObjectMasterId INT = NULL OUTPUT', @tblEmailIds

我收到以下错误

Msg 214, Level 16, State 3, Procedure sp_executesql, Line 6 Procedure expects parameter '@params' of type 'ntext/nchar/nvarchar'.

SP_EXECUTESQL@params 的前缀 N

您还需要存储 OUTPUT 参数的结果

Declare  @IdsCSV NVARCHAR(MAX),@ObjectMasterId INT = NULL

EXECUTE SP_EXECUTESQL 
    @SqlQuery,
    N'@IdsCSV NVARCHAR(MAX) OUTPUT,@ObjectMasterId INT = NULL OUTPUT',
    @IdsCSV = @IdsCSV OUTPUT,
    @ObjectMasterId = @ObjectMasterId OUTPUT

这里有不少问题。

  1. 正如错误消息明确指出的那样,参数列表需要 NVARCHAR 所以只需在该字符串文字前加上 N (正如@VR46 的回答中所述) .

  2. Table 变量无法按照您尝试使用它们的方式工作。首先,你永远不会声明 @tblEmailIds,但即使你声明了,table 变量的范围也是局部的,它们不能用作 OUTPUT 参数。相反,您需要创建一个本地临时 table(即 #tblEmailIds)并执行 INSERT INTO #tblEmailIds.

  3. 您引用了另一个尚未声明或填充的 table 变量 @tbleRecipientsTypes

  4. 您确实声明了 @tempIsObjectSpecific 但从未设置它,因此它将始终是 NULL.

  5. 为什么@IdsCSV(在sp_executesql调用参数列表中)声明为OUTPUT?您不仅没有传入 @tempRecipientsIdsCSV(动态 SQL 中的 @IdsCSV),甚至不需要作为参数,因为您直接连接 [= 的值22=] 进入动态 SQL,动态 SQL 中没有 @tempRecipientsIdsCSV 变量开始。所以从参数列表中删除@IdsCSV NVARCHAR(MAX) OUTPUT,

  6. 你说“@tempRecipientsIdsCSV 是我的 SP 接受的第一个参数”,但是你在代码中声明它,这应该会导致错误。

  7. @ObjectMasterId 是什么数据类型?你说它被传递到 proc 中,我看到它被连接到动态 SQL 中,因此它需要是字符串类型(即不是 INT 中显示的 [=20] =] 参数列表)或者它需要在 CONVERT(NVARCHAR(10), @ObjectMasterId.

  8. 如果传入的是@ObjectMasterId,那么为什么在sp_executesql参数列表中声明为OUTPUT呢?但更好的问题可能是:既然你直接将它连接到动态 SQL,你为什么还要将它传递到 sp_executesql?动态 SQL.

  9. 中没有使用 @ObjectMasterId 变量