当前位置:   article > 正文

实现分页查询的一种方法,使用Microsoft SQL Server数据库_sql server 分页查询

sql server 分页查询

数据库均提供了分页查询的语句和相应的方法,但是如果查询的结果较为复杂,如查询结果需要结过再计算、分段、添加汇总行等操作后再输出,就需要考虑的更为全面一些,而且还要配合前端实现的逻辑。本文是在实践中用到一种方法,仅供参考。

一、SQL语言用于分页的语句

在最新版本的Microsoft SQL Server中,分页查询通常是通过使用OFFSETFETCH NEXT子句来实现的。这种方法是在SQL Server 2012及以后的版本中引入的,它提供了一种更直观和高效的方式来进行分页。
以下是一个使用OFFSETFETCH NEXT进行分页查询的基本示例:

SELECT *
FROM YourTable
ORDER BY SomeColumn
OFFSET (@pageIndex - 1) * @pageSize ROWS
FETCH NEXT @pageSize ROWS ONLY;
  • 1
  • 2
  • 3
  • 4
  • 5

在这个例子中:

  • @pageIndex 表示当前页码,它是一个变量,代表用户请求的页码。
  • @pageSize 表示每页显示的记录数,它也是一个变量。
  • OFFSET 用于跳过指定数量的行,计算方式是(当前页码 - 1) * 每页记录数
  • FETCH NEXT 用于限制结果集只返回接下来的指定数量的行,即每页的记录数。
    这种方法的优点是它简单、直观,并且性能良好,特别是在处理大量数据时。它避免了在旧版本中常用的一些复杂方法,如使用ROW_NUMBER()函数或者多次查询来确定行的偏移量。
    请注意,为了使用这种方法,你需要确保你的SQL Server版本至少是2012或更高版本。如果你使用的是更早的版本,你可能需要使用其他方法,如ROW_NUMBER()或者CURSOR等。

二、后端过程设计示例

USE [hyX1201]
GO
/****** Object:  StoredProcedure [dbo].[X9_ZZCH_MXZZ]    Script Date: 2024-03-21 15:39:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ==================================================================================
-- Author:		昆山华岳软件有限公司 岳国军
-- Script Date: 2023-11-30
-- Description:	总账查询:存货总账_明细总账 分页查询示例程序,本例不使用存储表
-- ===================================================================================
ALTER PROCEDURE [dbo].[X9_ZZCH_MXZZ]
	(@KSNY CHAR(6),
	@JSNY CHAR(6),
	@CKMC NVARCHAR(50),
	@CXYC INT,@CXHS INT,@RQSJ VARCHAR(30))
	--查询页次:-1 获取总行数,>=0 查询的页次,
	--查询行数:每页查询行数,
	--日期时间:可用于命名临时表,由前端生成
AS
	DECLARE	@LJZD VARCHAR(100);
	SET @LJZD ='存货明细账查询';
	IF @CXYC=-2
		RETURN;
	IF @CXYC=-1
		BEGIN
			--返回结果行数
			WITH MXZZ (CHXH,CHDH,CHMC,XH1,XH2,XH3,GG1,JLDW,QCSL,QCJS,QCJE,SRSL,SRJS,SRJE,FCSL,FCJS,FCJE,JCSL,JCJS,JCJE) AS 
				(SELECT XM.CHXH, XM.CHDH, XM.CHMC, XM.XH1, XM.XH2, XM.XH3, XM.GG1, XM.JLDW,
					SUM(CASE ZZ.NY WHEN @KSNY THEN ZZ.QCSL ELSE 0 END) AS QCSL, 
					SUM(CASE ZZ.NY WHEN @KSNY THEN ZZ.QCJS ELSE 0 END) AS QCJS, 
					SUM(CASE ZZ.NY WHEN @KSNY THEN ZZ.QCJE ELSE 0 END) AS QCJE, 
					SUM(ZZ.SRSL) AS SRSL, SUM(ZZ.SRJS) AS SRJS, SUM(ZZ.SRJE) AS SRJE, SUM(ZZ.FCSL) AS FCSL, 
					SUM(ZZ.FCJS) AS FCJS, SUM(ZZ.FCJE) AS FCJE, 
					SUM(CASE ZZ.NY WHEN @JSNY THEN ZZ.JCSL ELSE 0 END) AS JCSL, 
					SUM(CASE ZZ.NY WHEN @JSNY THEN ZZ.JCJS ELSE 0 END) AS JCJS, 
					SUM(CASE ZZ.NY WHEN @JSNY THEN ZZ.JCJE ELSE 0 END) AS JCJE
				FROM UTZZCH AS ZZ INNER JOIN MLCHXM AS XM ON ZZ.CHXH = XM.CHXH
				WHERE (ZZ.CKMC=@CKMC OR @CKMC='') AND (ZZ.NY BETWEEN @KSNY AND @JSNY)
				GROUP BY XM.CHXH, XM.CHDH, XM.CHMC, XM.XH1, XM.XH2, XM.XH3, XM.GG1, XM.JLDW)
			SELECT COUNT(*) AS CXHS FROM MXZZ ;	
		END
	IF @CXYC>-1
		BEGIN
			--返回当前页所需要查询结果 
			WITH MXZZ (CHXH,CHDH,CHMC,XH1,XH2,XH3,GG1,JLDW,QCSL,QCJS,QCJE,SRSL,SRJS,SRJE,FCSL,FCJS,FCJE,JCSL,JCJS,JCJE) AS 
				(SELECT XM.CHXH, XM.CHDH, XM.CHMC, XM.XH1, XM.XH2, XM.XH3, XM.GG1, XM.JLDW,
					SUM(CASE ZZ.NY WHEN @KSNY THEN ZZ.QCSL ELSE 0 END) AS QCSL, 
					SUM(CASE ZZ.NY WHEN @KSNY THEN ZZ.QCJS ELSE 0 END) AS QCJS, 
					SUM(CASE ZZ.NY WHEN @KSNY THEN ZZ.QCJE ELSE 0 END) AS QCJE, 
					SUM(ZZ.SRSL) AS SRSL, SUM(ZZ.SRJS) AS SRJS, SUM(ZZ.SRJE) AS SRJE, SUM(ZZ.FCSL) AS FCSL, 
					SUM(ZZ.FCJS) AS FCJS, SUM(ZZ.FCJE) AS FCJE, 
					SUM(CASE ZZ.NY WHEN @JSNY THEN ZZ.JCSL ELSE 0 END) AS JCSL, 
					SUM(CASE ZZ.NY WHEN @JSNY THEN ZZ.JCJS ELSE 0 END) AS JCJS, 
					SUM(CASE ZZ.NY WHEN @JSNY THEN ZZ.JCJE ELSE 0 END) AS JCJE
				FROM UTZZCH AS ZZ INNER JOIN MLCHXM AS XM ON ZZ.CHXH = XM.CHXH
				WHERE (ZZ.CKMC=@CKMC OR @CKMC='') AND (ZZ.NY BETWEEN @KSNY AND @JSNY)
				GROUP BY XM.CHXH, XM.CHDH, XM.CHMC, XM.XH1, XM.XH2, XM.XH3, XM.GG1, XM.JLDW)
			SELECT CHXH,CHDH,CHMC,XH1,XH2,XH3,GG1,JLDW,QCSL,QCJS,
				CASE WHEN QCSL<>0 THEN QCJE/QCSL ELSE 0 END AS QCDJ,QCJE,
				SRSL,SRJS,SRJE,FCSL,FCJS,FCJE,JCSL,
				CASE WHEN JCSL>0 THEN JCJE/JCSL ELSE 0 END AS JCDJ,JCJS,JCJE,@LJZD AS 链接功能 FROM MXZZ
			ORDER BY CHDH,CHXH  offset (@CXYC*@CXHS)  rows fetch next @CXHS rows only;	
			RETURN;
		END
RETURN;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

三、前端实现逻辑

  '由前端定义每次查询的行数
  Public pCXHS As Integer = 25		'查询行数,不再存储本地文件
  Dim DqPage As Integer = 0			'当前页
  Dim EndPage As Integer = 0		'最后一页
  Dim CXrqsj As String = ...		'定义一时间戳
  Dim CXsql As String = ""
  dim Dt1 as DataTable
  dim Sql1 as String 				'原来的查询语句。	
  ...... sql1根据前端定义赋值
  EndPage = -1
  If InStr(UCase(Sql1), "<CXYC>") > 0 And InStr(UCase(Sql1), "<CXHS>") > 0 Then
      Dim CRsql As String = Replace(CXsql, "<CXYC>", "-1")
      CRsql = Replace(CRsql, "<CXHS>", pCXHS)
      CRsql = Replace(CRsql, "<RQSJ>", CXrqsj)
      '初次查询时获取总行数
      Dim cxrows As Integer = GetDBInteger(CRsql)
      If cxrows <= 0 Then
          Exit Sub
      End If
      '计算出最大页号
      EndPage = cxrows \ pCXHS
      If (cxrows Mod pCXHS) = 0 Then
          EndPage -= 1
      End If
      L3.Caption = "共[" & cxrows.ToString.Trim & "]行记录,分" & (EndPage + 1).ToString.Trim & "页查询"
  Else
      L3.Caption = ""
  End If
  ......根据前端查询状态确定当前页次后查询相应页次的数据
  Dt1 = New DataTable
  Dim Sql1 As String
  Sql1 = Replace(CXsql, "<CXYC>", DqPage)
  Sql1 = Replace(Sql1, "<CXHS>", pCXHS)
  Sql1 = Replace(Sql1, "<RQSJ>", CXrqsj)
  Dt1 = GetDTread(Sql1)
  If IsNothing(Dt1) Then
      XXshow("数据未能正确载入", Me)
      Exit Sub
  End If
  GridCX.DataSource = Nothing
  GridCX.DataSource = Dt1
  Gdgv.RefreshData()
  '更新翻页按钮状态
  Btpg1.Enabled = (DqPage > 0) And (EndPage > 0)
  Btpg2.Enabled = (DqPage > 0) And (EndPage > 0)
  Btpg3.Enabled = (DqPage < EndPage) And (EndPage > 0)
  Btpg4.Enabled = (DqPage < EndPage) And (EndPage > 0)
  Lczs.Text = " 第 " & (DqPage + 1).ToString.Trim & " 页 共 " & (EndPage + 1).ToString.Trim & " 页 "
  ...... 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

总结

如果查询结果行数非常多或需要的计算较为复杂,应在初次查询使用(返回行数)时,将查询结果存在临时表中,后面查询就可以从此查询了。总之,不管什么方法,都是需要前端合理配合,才能收到更好的效果。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/334044
推荐阅读
相关标签
  

闽ICP备14008679号