我不擅长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
之后使用 OFFSET
和 FETCH
来实现分页(请参阅 here )。在这种情况下,SQL 语句看起来非常接近使用 OFFSET
和 LIMIT
的相应 MySQL 或 PostgreSQL 语句。顺便说一下微软 Entity Framework 使用 Entity SQL Language具有紧密的构造(SKIP
和 LIMIT
)。如果您使用 SQL Server 2012 或更高版本,OFFSET
和 FETCH
可能是首选方式。
因为您在问题中包含了 SQL Server 2008 标记,所以我不会在答案中使用新的 SQL Server 2012 结构。
另一个好方法是使用 sp_executesql
,它允许您将 SQL 语句构造为带参数的字符串。它允许重用执行计划,这对于获得最佳性能非常重要。该方法允许您扩展存储过程
的代码以实现服务器端过滤(搜索)。
我发现需要在 SQL 语句中实现分页,其中包含返回数据的 ID(在您的情况下为 PersonId
)。因此,我决定建议您使用简化的方式,将SELECT TOP
与LEFT 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/