Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 基于参数(不包括pagesize参数)的参数化存储过程分页返回行计数_Sql Server_Tsql_Stored Procedures_Parameters - Fatal编程技术网

Sql server 基于参数(不包括pagesize参数)的参数化存储过程分页返回行计数

Sql server 基于参数(不包括pagesize参数)的参数化存储过程分页返回行计数,sql-server,tsql,stored-procedures,parameters,Sql Server,Tsql,Stored Procedures,Parameters,我希望能够从存储过程中获取查询的行数,但不考虑分页的pagesize限制 以下是我的存储过程: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[OrderLoadAllPaged] @OrderId INT = 0, @WarehouseId INT = 0, @PaymentMethodSystemName NVARCHAR(MAX) = NULL, @OrderS

我希望能够从存储过程中获取查询的行数,但不考虑分页的pagesize限制

以下是我的存储过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[OrderLoadAllPaged]
    @OrderId INT = 0,
    @WarehouseId INT = 0,
    @PaymentMethodSystemName NVARCHAR(MAX) = NULL,
    @OrderStatusId INT = 0,
    @PaymentStatusId INT = 0,
    @ShippingStatusId INT = 0,
    @BillingEmail NVARCHAR(MAX) = NULL,
    @BillingFirstName NVARCHAR(MAX) = NULL,
    @BillingLastName NVARCHAR(MAX) = NULL,
    @ShippingMethod NVARCHAR(MAX) = NULL,
    @CreatedFromUtc DATETIME = NULL,
    @CreatedToUtc DATETIME = NULL,
    @PageIndex INT = 0, 
    @PageSize INT = 2147483644,
    @TotalRecords INT = NULL OUTPUT
AS
BEGIN
    DECLARE @sql NVARCHAR(MAX)

    SET NOCOUNT ON;

    SELECT TOP (@PageSize) *
    FROM [Test].[dbo].[Order] o WITH (NOLOCK)
    LEFT JOIN
        (SELECT * 
         FROM [Test].[dbo].[Address] a 
         WHERE (@BillingEmail IS NULL OR a.[Email] = @BillingEmail)
           AND (@BillingFirstName IS NULL OR a.[FirstName] = @BillingFirstName)
           AND (@BillingLastName IS NULL OR a.[LastName] = @BillingLastName)) a 
         ON a.Id = o.BillingAddressId
         AND o.[Deleted] = 0
         AND (o.[Id] = @OrderId OR @OrderId = 0)
         AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)
         AND (@PaymentMethodSystemName IS NULL OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)
         AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
         AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)
         AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)
         AND (@ShippingMethod IS NULL OR o.[ShippingMethod] = @ShippingMethod)
         AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
         AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')
         AND o.[Id] >= @PageIndex
         AND o.[Id] < @PageSize
    ORDER BY 
        o.[CreatedOnUtc] DESC 
        -- OFFSET @PageIndex ROWS FETCH NEXT @PageSize ROWS ONLY

    --total records
    SET @TotalRecords = @@rowcount
END
更新 我有分页的工作,但它不太正确。它从我的订单表返回记录的总数,但这就像插入到TENTOTAL表中的参数被忽略一样。我想我弄错了

代码如下:

create table #TempTotal (RowNum int identity(1,1), id int);
create index #IK_temp on #TempTotal (id);
-- Insert statements for procedure here
--select all
INSERT INTO #TempTotal ([id])
    SELECT o.[Id]
    FROM [Test].[dbo].[Order] o with (NOLOCK)

left join 
    (select * from [Test].[dbo].[Address] a 
        where (@BillingEmail IS null OR a.[Email] = @BillingEmail)
        AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
        AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)) a
        ON a.Id = o.BillingAddressId

AND o.[Deleted] = 0
AND (o.[Id] = @OrderId OR @OrderId = 0)
AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)
AND (@PaymentMethodSystemName IS NULL OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)
AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)
AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)
AND (@ShippingMethod IS NULL OR o.[ShippingMethod] = @ShippingMethod)
AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')
ORDER BY o.[CreatedOnUtc] DESC

-- Return the paged records
select TOP (@PageSize) *
from [Test].[dbo].[Order] ord
where ord.Id in (
      select id
      from #TempTotal
      Where (ord.[Id] >= @PageIndex AND ord.[Id] < @PageSize)

)
ORDER BY ord.[CreatedOnUtc] DESC;
更新3 我还必须更新分页以计算索引,我的cms将pageindex发送为page1、2、3等等。你的情况可能需要类似的东西。完整代码如下所示:

有两种选择:

复制不带顶部的查询以获取计数*

按原样使用查询以获取id并将其插入包含标识列RowNum的临时表中,然后使用该列进行分页,然后在获取实际记录之前获取计数,例如

选项2的性能将显著提高,因为它减少了SQL Server必须处理的数据量

作为旁白,您永远不应该选择*因为它会导致意外的、潜在的不良行为。始终列出您的列。

有几个选项:

复制不带顶部的查询以获取计数*

按原样使用查询以获取id并将其插入包含标识列RowNum的临时表中,然后使用该列进行分页,然后在获取实际记录之前获取计数,例如

选项2的性能将显著提高,因为它减少了SQL Server必须处理的数据量

作为旁白,您永远不应该选择*因为它会导致意外的、潜在的不良行为。始终列出您的列。

尝试使用CTE

SET @lFirstRec = ( @PageIndex – 1 ) * @PageSize 
         SET @lLastRec = ( @PageIndex * @PageSize + 1 )
         SET @lTotalRows = @lFirstRec – @lLastRec + 1

    ; WITH CTE_Results
             AS (
             SELECT ROW_NUMBER() OVER (ORDER BY o.Id                       
           ) AS ROWNUM,
           Count(*) over () AS TotalCount,
           * 
       from [Test].[dbo].[Address] a 
        where (@BillingEmail IS null OR a.[Email] = @BillingEmail)
        AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
        AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)) a
        ON a.Id = o.BillingAddressId

    AND
        o.[Deleted] = 0

    AND (o.[Id] = @OrderId OR @OrderId = 0)

    AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)

    AND (@PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)

    AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
    AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)

    AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)

    AND (@ShippingMethod IS null OR o.[ShippingMethod] = @ShippingMethod)

    AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
    AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')
    )
    SELECT
        TotalCount,
        ROWNUM,
        CPC.*
    FROM CTE_Results AS CPC
    WHERE
             ROWNUM > @lFirstRec
                   AND ROWNUM < @lLastRec
     ORDER BY CPC.CreatedOnUtc DESC, ROWNUM ASC
有关方法的更多详细信息,请参阅:

试试CTE

SET @lFirstRec = ( @PageIndex – 1 ) * @PageSize 
         SET @lLastRec = ( @PageIndex * @PageSize + 1 )
         SET @lTotalRows = @lFirstRec – @lLastRec + 1

    ; WITH CTE_Results
             AS (
             SELECT ROW_NUMBER() OVER (ORDER BY o.Id                       
           ) AS ROWNUM,
           Count(*) over () AS TotalCount,
           * 
       from [Test].[dbo].[Address] a 
        where (@BillingEmail IS null OR a.[Email] = @BillingEmail)
        AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
        AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)) a
        ON a.Id = o.BillingAddressId

    AND
        o.[Deleted] = 0

    AND (o.[Id] = @OrderId OR @OrderId = 0)

    AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)

    AND (@PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)

    AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
    AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)

    AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)

    AND (@ShippingMethod IS null OR o.[ShippingMethod] = @ShippingMethod)

    AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
    AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')
    )
    SELECT
        TotalCount,
        ROWNUM,
        CPC.*
    FROM CTE_Results AS CPC
    WHERE
             ROWNUM > @lFirstRec
                   AND ROWNUM < @lLastRec
     ORDER BY CPC.CreatedOnUtc DESC, ROWNUM ASC
有关方法的更多详细信息,请参阅:


@chrisc我不能在看不到实际代码的情况下判断发生了什么,但是如果操作正确,它应该给出与分页之前相同的行数。如果你把它分解并测试一下,解决它应该不会太难。是的,删除临时表可能是一个好主意,它们确实会随着连接自动删除,但是专门删除它们是一个很好的做法。我非常确定,您已经创建了一个巨大的连接,并且o.[Deleted]=0应该在o.[Deleted]的位置 = 0@chrisc注意,我更改了临时表索引-我最初给出的索引是用于不同的内容。@chrisc再次更新以使用偏移量。。。fetch next是推荐的方法。仍然会在同一时间生成相同的结果。使用推荐的方法offset@PageStart-1 rows fetch next@Pagesize rows,运行速度会更快only@chrisc在看不到实际代码的情况下,我无法判断发生了什么,但如果操作正确,它将给出与分页之前相同的行数。如果你把它分解并测试一下,解决它应该不会太难。是的,删除临时表可能是一个好主意,它们确实会随着连接自动删除,但是专门删除它们是一个很好的做法。我非常确定,您已经创建了一个巨大的连接,并且o.[Deleted]=0应该在o.[Deleted]的位置 = 0@chrisc注意,我更改了临时表索引-我最初给出的索引是用于不同的内容。@chrisc再次更新以使用偏移量。。。fetch next是推荐的方法。仍然在同一时间生成相同的结果。使用推荐的方法offset@PageStart-1 rows fetch next@Pagesize rows,运行速度会更快
-- Return the paged records
    select TOP (@PageSize) *
    from [Test].[dbo].[Order] ord
    where ord.Id in (
      select id
      from #TempTotal
      Where (ord.[Id] > @PageIndex)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[OrderLoadAllPaged]
    @OrderId INT = 0,
    @WarehouseId INT = 0,
    @PaymentMethodSystemName NVARCHAR(MAX) = NULL,
    @OrderStatusId INT = 0,
    @PaymentStatusId INT = 0,
    @ShippingStatusId INT = 0,
    @BillingEmail NVARCHAR(MAX) = NULL,
    @BillingFirstName NVARCHAR(MAX) = NULL,
    @BillingLastName NVARCHAR(MAX) = NULL,
    @ShippingMethod NVARCHAR(MAX) = NULL,
    @CreatedFromUtc DATETIME = NULL,
    @CreatedToUtc DATETIME = NULL,
    @PageIndex INT = 0, 
    @PageSize INT = 2147483644,
    @TotalRecords INT = NULL OUTPUT
AS
BEGIN
    DECLARE @sql NVARCHAR(MAX)

    SET NOCOUNT ON;

    create table #TempTotal (RowNum int identity(1,1), id int);
    create index #IK_temp on #TempTotal (RowNum);
    -- Insert statements for procedure here
    --select all
    INSERT INTO #TempTotal ([id])
        SELECT o.[Id]
        FROM [Test].[dbo].[Order] o with (NOLOCK)

    LEFT join [Test].[dbo].[Address] a on a.Id = o.BillingAddressId and (
        coalesce(@BillingEmail,'') <> ''
        or coalesce(@BillingFirstName,'') <> ''
        or coalesce(@BillingLastName,'') <> ''
    )
    WHERE (@BillingEmail IS null OR a.[Email] = @BillingEmail)
    AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
    AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)

    AND o.[Deleted] = 0
         AND (o.[Id] = @OrderId OR @OrderId = 0)
         AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)
         AND (@PaymentMethodSystemName IS NULL OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)
         AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
         AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)
         AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)
         AND (@ShippingMethod IS NULL OR o.[ShippingMethod] = @ShippingMethod)
         AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
         AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')
ORDER BY o.[CreatedOnUtc] DESC;

--paging
    DECLARE @PageLowerBound int
    SET @PageLowerBound = @PageSize * @PageIndex

-- Return the paged records
    select TOP (@PageSize) *
    from [Test].[dbo].[Order] ord
    where ord.[Id] in (
      select id
      from #TempTotal tt
      Where (tt.RowNum > @PageLowerBound)

    )ORDER BY ord.[CreatedOnUtc] DESC;

    --total records
    select @TotalRecords = count(*) from #TempTotal; -- To get the total record count

    DROP TABLE #TempTotal
END

    create table #temp (id int, RowNum int identity(1,1));
    create index #IK_temp on #temp (RowNum);

    -- insert your ids from your full query here

    -- Assign your total record count
    select @TotalRecords = count(*) from #temp; -- To get the total record count

    -- Return the paged records
    select *
    from MyTable
    where id in (
      select id
      from #temp
      order by RowNum asc
      offset (@PageStart-1) rows fetch next @Pagesize rows only
    );
SET @lFirstRec = ( @PageIndex – 1 ) * @PageSize 
         SET @lLastRec = ( @PageIndex * @PageSize + 1 )
         SET @lTotalRows = @lFirstRec – @lLastRec + 1

    ; WITH CTE_Results
             AS (
             SELECT ROW_NUMBER() OVER (ORDER BY o.Id                       
           ) AS ROWNUM,
           Count(*) over () AS TotalCount,
           * 
       from [Test].[dbo].[Address] a 
        where (@BillingEmail IS null OR a.[Email] = @BillingEmail)
        AND (@BillingFirstName IS null OR a.[FirstName] = @BillingFirstName)
        AND (@BillingLastName IS null OR a.[LastName] = @BillingLastName)) a
        ON a.Id = o.BillingAddressId

    AND
        o.[Deleted] = 0

    AND (o.[Id] = @OrderId OR @OrderId = 0)

    AND (o.[WarehouseId] = @WarehouseId OR @WarehouseId = 0)

    AND (@PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = @PaymentMethodSystemName)

    AND (o.[OrderStatusId] = @OrderStatusId OR @OrderStatusId = 0)
    AND (o.[PaymentStatusId] = @PaymentStatusId OR @PaymentStatusId = 0)

    AND (o.[ShippingStatusId] = @ShippingStatusId OR @ShippingStatusId = 0)

    AND (@ShippingMethod IS null OR o.[ShippingMethod] = @ShippingMethod)

    AND o.[CreatedOnUtc] >= ISNULL(@CreatedFromUtc, '1/1/1900')
    AND o.[CreatedOnUtc] < ISNULL(@CreatedToUtc, '1/1/2999')
    )
    SELECT
        TotalCount,
        ROWNUM,
        CPC.*
    FROM CTE_Results AS CPC
    WHERE
             ROWNUM > @lFirstRec
                   AND ROWNUM < @lLastRec
     ORDER BY CPC.CreatedOnUtc DESC, ROWNUM ASC