sql-server-2008 - 如何在存储过程中对jqGrid进行分页?

标签 sql-server-2008 stored-procedures jqgrid pagination jqgrid-asp.net

我不擅长sql,但我必须在有很多记录的存储过程中对jqGrid进行分页。我的asp.net mvc3 Controller 代码如下,

[HttpPost]
    public JsonResult GetExtraPersons(int cId, long pId, JQGridSettings gridSettings)
    {
        List<ExtraPerson> extraPersons = new List<ExtraPerson>();            
        ExtraPersonViewModel extraPersonViewModel = new ExtraPersonViewModel();
        extraPersonViewModel.CampId = cId;
        extraPersonViewModel.ReferencePatientId = pId;

        extraPersons = ExtraPersonService.GetExtraPersons(extraPersonViewModel.CampId, extraPersonViewModel.ReferencePatientId);

        int pageIndex = gridSettings.pageIndex;
        int pageSize = gridSettings.pageSize;
        int totalRecords = extraPersons.Count;
        int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);

        int startRow = (pageIndex - 1) * pageSize;
        int endRow = startRow + pageSize;

        var jsonData = new
        {
            total = totalPages,
            page = pageIndex,
            records = totalRecords,
            rows =
            (
              extraPersons.Select(e => new
              {
                  Id = e.ExtraPersonId,                
                  FirstName = e.FirstName,
                  LastName = e.LastName,
                  MobilePhone = e.MobileNumber,
                  Email = e.EmailId,
                  PersonalNumber = e.PersonNumber,
                  Diabetes = e.Diabetes, 
                  BloodPressure = e.BloodPressure,
              })
            ).ToArray()
        };
        return Json(jsonData);
    }

以及我在sql server 2008中的存储过程如下,

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetExtraPerson] 
(
@CampId INT,
@ReferencePatientId BIGINT
)


AS  

BEGIN  
SET NOCOUNT ON         

SELECT  

PERS.PersonId,  
PERS.FirstName,  
PERS.LastName,  
PERS.MobileNumber,
PERS.EmailId,
PERS.PersonNumber,
E.ExtraPersonId,
E.Diabetes,
E.BloodPressure

FROM  
ExtraPerson E  
INNER JOIN Person PERS  
ON PERS.PersonId=E.PersonId  



WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId AND E.IsDeleted = 0
END

现在jqGrid除了分页外都工作正常。例如:如果有 15 条记录,第一页显示 10 条记录,剩余的在第二页,但我无法转到它。 谁能建议我,如何为 jqgrid 进行分页?

最佳答案

有很多方法可以实现您需要的STORED PROCEDURE。例如,您可以在 CTE SQL 语句内使用 ROW_NUMBER 构造。

如果您使用 SQL Server 2012,则可以在 ORDER BY 之后使用 OFFSETFETCH 来实现分页(请参阅 here )。在这种情况下,SQL 语句看起来非常接近使用 OFFSETLIMIT 的相应 MySQL 或 PostgreSQL 语句。顺便说一下微软 Entity Framework 使用 Entity SQL Language具有紧密的构造(SKIPLIMIT)。如果您使用 SQL Server 2012 或更高版本,OFFSETFETCH 可能是首选方式。

因为您在问题中包含了 SQL Server 2008 标记,所以我不会在答案中使用新的 SQL Server 2012 结构。

另一个好方法是使用 sp_executesql,它允许您将 SQL 语句构造为带参数的字符串。它允许重用执行计划,这对于获得最佳性能非常重要。该方法允许您扩展存储过程的代码以实现服务器端过滤(搜索)。

我发现需要在 SQL 语句中实现分页,其中包含返回数据的 ID(在您的情况下为 PersonId)。因此,我决定建议您使用简化的方式,将SELECT TOPLEFT OUTER JOIN结合使用。

存储过程dbo.GetExtraPerson可以有两个int类型的附加参数:@skip@pageSize。如果@skip等于0,则STORED PROCEDURE可以执行

SELECT TOP (@pageSize) PERS.PersonId
    ,PERS.FirstName
    ,PERS.LastName
    ,PERS.MobileNumber
    ,PERS.EmailId
    ,PERS.PersonNumber
    ,E.ExtraPersonId
    ,E.Diabetes
    ,E.BloodPressure
FROM ExtraPerson E  
    INNER JOIN Person PERS ON PERS.PersonId=E.PersonId  
WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId AND E.IsDeleted=0

如果@skip不等于0则对应的SQL语句可以是以下

WITH GetAll AS (
    SELECT PERS.PersonId
        ,PERS.FirstName
        ,PERS.LastName
        ,PERS.MobileNumber
        ,PERS.EmailId
        ,PERS.PersonNumber
        ,E.ExtraPersonId
        ,E.Diabetes
        ,E.BloodPressure
    FROM ExtraPerson E  
        INNER JOIN Person PERS ON PERS.PersonId=E.PersonId  
    WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId AND E.IsDeleted=0
),GetFirst AS (
    SELECT TOP (@skip) *
    FROM GetAll
    ORDER BY Name
),GetNext AS (
    SELECT TOP (@pageSize) a.*
    FROM GetAll AS a
        LEFT OUTER JOIN GetFirst AS f ON f.Id=a.Id
    WHERE f.Id IS NULL
    ORDER BY Name
)
SELECT * FROM GetNext 

dbo.GetExtraPerson的完整代码可能如下

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE dbo.GetExtraPerson 
    @CampId int,
    @ReferencePatientId bigint,
    @skip int,
    @pageSize int
AS
BEGIN
    DECLARE @records int;
    SET NOCOUNT ON;

    SET @records = (SELECT COUNT(*)
                    FROM ExtraPerson E  
                        INNER JOIN Person PERS ON PERS.PersonId=E.PersonId  
                    WHERE E.CampId=@CampId
                        AND ReferencePatientId=@ReferencePatientId
                        AND E.IsDeleted=0);

    IF @skip <= 0
        SELECT TOP (@pageSize) PERS.PersonId
            ,PERS.FirstName
            ,PERS.LastName
            ,PERS.MobileNumber
            ,PERS.EmailId
            ,PERS.PersonNumber
            ,E.ExtraPersonId
            ,E.Diabetes
            ,E.BloodPressure
        FROM ExtraPerson E  
            INNER JOIN Person PERS ON PERS.PersonId=E.PersonId  
        WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId
            AND E.IsDeleted=0
    ELSE
        WITH GetAll AS (
            SELECT PERS.PersonId
                ,PERS.FirstName
                ,PERS.LastName
                ,PERS.MobileNumber
                ,PERS.EmailId
                ,PERS.PersonNumber
                ,E.ExtraPersonId
                ,E.Diabetes
                ,E.BloodPressure
            FROM ExtraPerson E  
                INNER JOIN Person PERS ON PERS.PersonId=E.PersonId  
            WHERE E.CampId=@CampId AND ReferencePatientId=@ReferencePatientId
                AND E.IsDeleted=0
        ),GetFirst AS (
            SELECT TOP (@skip) *
            FROM GetAll
            ORDER BY Name
        ),GetNext AS (
            SELECT TOP (@pageSize) a.*
            FROM GetAll AS a
                LEFT OUTER JOIN GetFirst AS f ON f.Id=a.Id
            WHERE f.Id IS NULL
            ORDER BY Name
        )
        SELECT * FROM GetNext;

    RETURN @records;
END
GO

上面的过程另外返回记录总数,您可以使用它来分配 totalRecords 值。

如果您将上述代码与 sp_executesql 结合使用,您可以轻松修改代码以在所有 SELECT TOP 语句中包含 ORDER BY ,这样返回的值将对应于用户在 jqGrid 中请求的排序顺序。

关于sql-server-2008 - 如何在存储过程中对jqGrid进行分页?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18297642/

相关文章:

c# - 返回受 SQL UPDATE 语句影响的行

sql-server - 如何调试在任何测试环境中似乎都无法重现的 SQL Server 数据问题?

sql - 我想要表格格式的选择查询结果,例如摘要报告

.net - Visual Studio 2003 的 VARCHAR(MAX) SqlParameter 输出大小

php - 存储过程 zend framework 2.2 tablegateway 中的多重选择问题

mysql - 在mysql中将时间乘以十进制值?

javascript - 如何隐藏 jQgrid 中的所有复选框?

sql-server - 允许特殊字符 SQL Server 2008

javascript - jqGrid:如何在搜索工具栏中隐藏特定的搜索字段

html - JqG​​rid 固定高度不按预期工作