分页与存储过程

sak*_*kir 2 sql t-sql sql-server stored-procedures

我正在尝试添加分页存储过程的排序功能。

我该怎么做,到目前为止,我已经创建了这个。它可以正常工作,但是在传递@sort参数时不起作用。

ALTER PROCEDURE [dbo].[sp_Mk]
 @page INT,
 @size INT,
 @sort nvarchar(50) ,
 @totalrow INT  OUTPUT
AS
BEGIN
    DECLARE @offset INT
    DECLARE @newsize INT

    IF(@page=0)
    begin
       SET @offset = @page;
       SET @newsize = @size
    end
    ELSE 
    begin
        SET @offset = @page+1;
        SET @newsize = @size-1
    end
    -- SET NOCOUNT ON added to prevent extra result sets from
    SET NOCOUNT ON;
    WITH OrderedSet AS
    (
      SELECT *,
          ROW_NUMBER() OVER (ORDER BY @sort DESC) AS 'Index'
      FROM [dbo].[Mk]  
    )
   SELECT * 
   FROM OrderedSet 
   WHERE [Index] BETWEEN @offset AND (@offset + @newsize) 

   SET @totalrow = (SELECT COUNT(*) FROM [dbo].[Mk])
END
Run Code Online (Sandbox Code Playgroud)

Tar*_*zan 10

我正在添加一个答案,因为许多其他答案都建议使用动态 SQL,这不是最佳实践。您可以使用OFFSET-FETCH子句添加分页,该子句为您提供了从结果集中仅获取一个窗口或结果页的选项。

注意OFFSET-FETCH只能与ORDER BY子句。

例子:

SELECT First Name + ' ' + Last Name FROM Employees 
ORDER BY First Name 
OFFSET 10 ROWS FETCH NEXT 5 ROWS ONLY;
Run Code Online (Sandbox Code Playgroud)

  • 我认为它目前(截至 2018 年 2 月)是首选解决方案,尽管我应该指出此选项仅自 MS SQL Server 2012 版起可用,请参阅:http://www.sqlservergeeks.com/t-sql-分页存储过程/ (4认同)

小智 8

createprocedure [dbo].[Procedurename]
@Id bigint,
@PageNumber int,
    @PageSize int,
    @Keyword nvarchar(100)
AS
Begin
set NoCount on;

IF(@PageNumber <=0)
    BEGIN
    SET @PageNumber = 1;
    END
    IF(@PageSize<=0)
    BEGIN
    SET @PageSize = 2147483647;
    END
    DECLARE @SkipRows int = (@PageNumber - 1) * @PageSize;


select * from tablename
where ('condition')
and (@Keyword is null or Name like '%'+ @Keyword + '%' or Description like '%'+@Keyword+'%')
order by Id asc 
OFFSET @SkipRows ROWS 
    FETCH NEXT @PageSize ROWS ONLY
return
End
Run Code Online (Sandbox Code Playgroud)


pet*_*erm 5

一种方法(可能不是最好的方法)是使用动态SQL

CREATE PROCEDURE [sp_Mk]
 @page INT,
 @size INT,
 @sort nvarchar(50) ,
 @totalrow INT  OUTPUT
AS
BEGIN
    DECLARE @offset INT
    DECLARE @newsize INT
    DECLARE @sql NVARCHAR(MAX)

    IF(@page=0)
      BEGIN
        SET @offset = @page
        SET @newsize = @size
       END
    ELSE 
      BEGIN
        SET @offset = @page*@size
        SET @newsize = @size-1
      END
    SET NOCOUNT ON
    SET @sql = '
     WITH OrderedSet AS
    (
      SELECT *, ROW_NUMBER() OVER (ORDER BY ' + @sort + ') AS ''Index''
      FROM [dbo].[Mk] 
    )
   SELECT * FROM OrderedSet WHERE [Index] BETWEEN ' + CONVERT(NVARCHAR(12), @offset) + ' AND ' + CONVERT(NVARCHAR(12), (@offset + @newsize)) 
   EXECUTE (@sql)
   SET @totalrow = (SELECT COUNT(*) FROM [Mk])
END
Run Code Online (Sandbox Code Playgroud)

这是SQLFiddle演示

  • 更好的解决方案是使用 OFFSET-FETCH 子句添加分页。 (2认同)