在SQL Server存储过程中使用表类型参数

时间:2018-09-12 07:18:27

标签: sql-server stored-procedures

我使用表类型参数(@listdraftIds)并拆分表中的数据与DB中的数据进行比较,但错误如下。帮帮我,谢谢。

 CREATE OR ALTER   PROCEDURE [dbo].[sp_sel_contract]
    (
        @listDraftId  nvarchar(max),
        @Page int,
        @PageNumber int,
        @TotalRecord int OUTPUT
    )
        AS
        BEGIN
        SET NOCOUNT ON

        BEGIN
        DECLARE @listdraftIds TABLE (draftIds nvarchar(max))
        INSERT INTO @listdraftIds VALUES(@listDraftId)

        DECLARE @sql varchar(MAX)
        SET @sql= ' ALTER DATABASE '+ quotename(db_name()) + ' SET COMPATIBILITY_LEVEL = 130 ';
        EXEC(@sql)

        END

        DECLARE @query NVARCHAR(MAX)
        DECLARE @newquery NVARCHAR(MAX)

        DECLARE @RowIndex int 
        SET @RowIndex = (@Page-1) * @PageNumber

        SET @query = ''

        SET @query = @query + ' SELECT DISTINCT'
        SET @query = @query + ' [d].[draft_id], '
        ...

        SET @query = @query + 'WHERE '
        SET @query = @query + ' [d].[del_flg] = ''FALSE'''

        SET @query = @query + 'AND '
        SET @query = @query + ' [d].[draft_id]  '
        SET @query = @query + 'IN ('
        SET @query = @query + ' SELECT  DISTINCT  '
        SET @query = @query + ' value AS draft_id '
        SET @query = @query + 'FROM '
        SET @query = @query + ' @listdraftIds '
        SET @query = @query + 'CROSS APPLY STRING_SPLIT(draftIds, '','') '
        SET @query = @query + 'WHERE '
        SET @query = @query + ' RTRIM(value) <> '''' )'

        PRINT  @query

        SET @newquery = '  SET @TotalRecord = (SELECT COUNT(*) FROM (' + @query +') AS t) '

        SET @newquery = @newquery + ' ORDER BY '
        SET @newquery = @newquery + '    [draft_date] DESC, [d].[draft_id] DESC, [g].[detail_no] ASC'
        SET @newquery = @newquery + '    OFFSET @RowIndex ROWS FETCH NEXT @PageNumber ROWS ONLY'  

        EXECUTE sp_executesql @newquery,
            @listDraftId = @listDraftId,
            @RowIndex = @RowIndex,
            @PageNumber = @PageNumber, 
            @TotalRecord = @TotalRecord OUTPUT
    END

Then Exec proc:

DECLARE @return_value int,
        @TotalRecord int

EXEC    @return_value = [dbo].[sp_sel_draft_condition_api1]
        @listDraftId = N'123,345',
        @Page = 1,
        @PageNumber = 20,
        @TotalRecord = @TotalRecord OUTPUT

SELECT  @TotalRecord as N'@TotalRecord'

SELECT  'Return Value' = @return_value

GO

错误:

  

第15级,州1,第3行的消息102       '30302'附近的语法不正确。

     

消息1087,第15级,州2,第3行       必须声明表变量“ @listdraftIds”。

     

第137层15级状态2行3       必须声明标量变量“ @PageNumber”。

1 个答案:

答案 0 :(得分:0)

存储过程在这里很少出现问题

首先,sp_executesql在其自己的上下文中执行。因此,无法识别在其外部声明的变量。这意味着,如果需要使用变量,则需要将其传递到sp_executesql中。

您的sp_executesql语句未定义任何变量

应该是

EXECUTE sp_executesql @newquery, 
                      N'@RowIndex int, @PageNumber int, @TotalRecord int OUTPUT',
                      @RowIndex    = @RowIndex,
                      @PageNumber  = @PageNumber, 
                      @TotalRecord = @TotalRecord OUTPUT

请注意,我没有包含@listDraftId。那是因为您不能将表变量传递到sp_executesql中。一种替代方法是使用临时表

所以在您的sp_sel_contract

create table #listdraftId ( draftIds nvarchar(max) )

然后您可以在动态查询中引用临时表#listdraftId

实际上,您在查看动态查询时,您不需要表变量或临时表。您只有一个值@listDraftId传递给sp_sel_contract,然后它才传递给动态查询。因此,您可以将该变量直接传递到动态查询中。示例:

EXECUTE sp_executesql @newquery, 
                  N'@listDraftId nvarchar(max), @RowIndex int, @PageNumber int, @TotalRecord int OUTPUT',
                  @listDraftId = @listDraftId,
                  @RowIndex    = @RowIndex,
                  @PageNumber  = @PageNumber, 
                  @TotalRecord = @TotalRecord OUTPUT

编辑: 现在我仔细看看您的动态查询?我完全不需要使用动态查询。您可以通过普通查询实现所需的目标