千家信息网

sql中怎么实现分页查询

发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,本篇文章为大家展示了sql中怎么实现分页查询,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1.创建测试环境,(插入100万条数据大概耗时5分钟)。create
千家信息网最后更新 2025年02月23日sql中怎么实现分页查询

本篇文章为大家展示了sql中怎么实现分页查询,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

1.创建测试环境,(插入100万条数据大概耗时5分钟)。

create database DBTestuse DBTest --创建测试表create table pagetest(id int identity(1,1) not null,col01 int null,col02 nvarchar(50) null,col03 datetime null) --1万记录集declare @i intset @i=0while(@i<10000)begin insert into pagetest select cast(floor(rand()*10000) as int),left(newid(),10),getdate() set @i=@i+1end

2.几种典型的分页sql下面例子是每页50条,198*50=9900,取第199页数据。

--写法1,not in/top

select top 50 * from pagetestwhere id not in (select top 9900 id from pagetest order by id)order by id

--写法2,not exists

select top 50 * from pagetestwhere not exists(select 1 from (select top 9900 id from pagetest order by id)a where a.id=pagetest.id)order by id

--写法3,max/top

select top 50 * from pagetestwhere id>(select max(id) from (select top 9900 id from pagetest order by id)a)order by id

--写法4,row_number()

select top 50 * from(select row_number()over(order by id)rownumber,* from pagetest)awhere rownumber>9900 select * from(select row_number()over(order by id)rownumber,* from pagetest)awhere rownumber>9900 and rownumber<9951 select * from(select row_number()over(order by id)rownumber,* from pagetest)awhere rownumber between 9901 and 9950

--写法5,在csdn上一帖子看到的,row_number() 变体,不基于已有字段产生记录序号,先按条件筛选以及排好序,再在结果集上给一常量列用于产生记录序号

select *from ( select row_number()over(order by tempColumn)rownumber,* from (select top 9950 tempColumn=0,* from pagetest where 1=1 order by id)a)bwhere rownumber>9900

3.分别在1万,10万(取1990页),100(取19900页)记录集下测试。

测试sql:

declare @begin_date datetimedeclare @end_date datetimeselect @begin_date = getdate()<.....YOUR CODE.....>select @end_date = getdate()select datediff(ms,@begin_date,@end_date) as '毫秒'

1万:基本感觉不到差异。

10万:

4.结论:

1.max/top,ROW_NUMBER()都是比较不错的分页方法。相比ROW_NUMBER()只支持sql2005及以上版本,max/top有更好的可移植性,能同时适用于sql2000,access。

2.not exists感觉是要比not in效率高一点点。

3.ROW_NUMBER()的3种不同写法效率看起来差不多。

4.ROW_NUMBER() 的变体基于我这个测试效率实在不好。原帖在这里 http://topic.csdn.net/u/20100617/04/80d1bd99-2e1c-4083-ad87-72bf706cb536.html

PS.上面的分页排序都是基于自增字段id。测试环境还提供了int,nvarchar,datetime类型字段,也可以试试。不过对于非主键没索引的大数据量排序效率应该是很不理想的。

5.简单将ROWNUMBER,max/top的方式封装到存储过程。

ROWNUMBER():ALTER PROCEDURE [dbo].[Proc_SqlPageByRownumber]( @tbName VARCHAR(255),   --表名 @tbGetFields VARCHAR(1000)= '*',--返回字段 @OrderfldName VARCHAR(255),  --排序的字段名 @PageSize INT=20,    --页尺寸 @PageIndex INT=1,    --页码 @OrderType bit = 0,    --0升序,非0降序 @strWhere VARCHAR(1000)='',  --查询条件 --@TotalCount INT OUTPUT   --返回总记录数)AS-- =============================================-- Author:  allen (liyuxin)-- Create date: 2012-03-30-- Description: 分页存储过程(支持多表连接查询)-- Modify [1]: 2012-03-30-- =============================================BEGIN DECLARE @strSql VARCHAR(5000) --主语句 DECLARE @strSqlCount NVARCHAR(500)--查询记录总数主语句 DECLARE @strOrder VARCHAR(300) -- 排序类型 --------------总记录数--------------- IF ISNULL(@strWhere,'') <>''    SET @strSqlCount='Select @TotalCout=count(*) from ' + @tbName + ' where 1=1 '+ @strWhere ELSE SET @strSqlCount='Select @TotalCout=count(*) from ' + @tbName  --exec sp_executesql @strSqlCount,N'@TotalCout int output',@TotalCount output --------------分页------------ IF @PageIndex <= 0 SET @PageIndex = 1 IF(@OrderType<>0) SET @strOrder=' ORDER BY '+@OrderfldName+' DESC ' ELSE SET @strOrder=' ORDER BY '+@OrderfldName+' ASC ' SET @strSql='SELECT * FROM  (SELECT ROW_NUMBER() OVER('+@strOrder+') RowNo,'+ @tbGetFields+' FROM ' + @tbName + ' WHERE 1=1 ' + @strWhere+' ) tb  WHERE tb.RowNo BETWEEN '+str((@PageIndex-1)*@PageSize+1)+' AND ' +str(@PageIndex*@PageSize) exec(@strSql) SELECT @TotalCountEND
public static SqlParameter MakeInParam(string ParamName, SqlDbType DbType, Int32 Size, object Value)  {   return MakeParam(ParamName, DbType,Size, ParameterDirection.Input, Value);  }  public static SqlParameter MakeOutParam(string ParamName, SqlDbType DbType)  {   return MakeParam(ParamName, DbType, 0, ParameterDirection.Output, null);  }  public static SqlParameter MakeParam(string ParamName, SqlDbType DbType, Int32 Size, ParameterDirection Direction, object Value)  {   SqlParameter param;   if (Size > 0)    param = new SqlParameter(ParamName, DbType, Size);   else    param = new SqlParameter(ParamName, DbType);   param.Direction = Direction;   if (!(Direction == ParameterDirection.Output && Value == null))    param.Value = Value;   return param;  }  ///   /// 分页获取数据列表及总行数  ///   /// 表名  /// 返回字段  /// 排序的字段名  /// 页尺寸  /// 页码  /// false升序,true降序  /// 查询条件  public static DataSet GetPageList(string tbName, string tbGetFields, string OrderFldName, int PageSize, int PageIndex, string strWhere)  {   SqlParameter[] parameters = {      MakeInParam("@tbName",SqlDbType.VarChar,255,tbName),      MakeInParam("@tbGetFields",SqlDbType.VarChar,1000,tbGetFields),       MakeInParam("@OrderfldName",SqlDbType.VarChar,255,OrderFldName),       MakeInParam("@PageSize",SqlDbType.Int,0,PageSize),       MakeInParam("@PageIndex",SqlDbType.Int,0,PageIndex),       MakeInParam("@OrderType",SqlDbType.Bit,0,OrderType),       MakeInParam("@strWhere",SqlDbType.VarChar,1000,strWhere),      // MakeOutParam("@TotalCount",SqlDbType.Int)      };   return RunProcedure("Proc_SqlPageByRownumber", parameters, "ds");  }

调用:

public DataTable GetList(string tbName, string tbGetFields, string OrderFldName, int PageSize, int PageIndex, string strWhere, ref int TotalCount)  {   DataSet ds = dal.GetList(tbName, tbGetFields, OrderFldName, PageSize, PageIndex, strWhere);   TotalCount = Convert.ToInt32(ds.Tables[1].Rows[0][0]);   return ds.Tables[0];  }

注意:多表连接时需注意的地方

1.必填项:tbName,OrderfldName,tbGetFields

2.实例:

tbName ="UserInfo u INNER JOIN Department d ON u.DepID=d.ID"  tbGetFields="u.ID AS UserID,u.Name,u.Sex,d.ID AS DepID,d.DefName"  OrderfldName="u.ID,ASC|u.Name,DESC" (格式:Name,ASC|ID,DESC)  strWhere:每个条件前必须添加 AND (例如:AND UserInfo.DepID=1 )

Max/top:(简单写了下,需要满足主键字段名称就是"id")

create proc [dbo].[spSqlPageByMaxTop]@tbName varchar(255),  --表名@tbFields varchar(1000),  --返回字段@PageSize int,    --页尺寸@PageIndex int,    --页码@strWhere varchar(1000), --查询条件@StrOrder varchar(255), --排序条件@Total int output   --返回总记录数asdeclare @strSql varchar(5000) --主语句declare @strSqlCount nvarchar(500)--查询记录总数主语句--------------总记录数---------------if @strWhere !=''beginset @strSqlCount='Select @TotalCout=count(*) from ' + @tbName + ' where '+ @strWhereendelsebeginset @strSqlCount='Select @TotalCout=count(*) from ' + @tbNameend--------------分页------------if @PageIndex <= 0begin set @PageIndex = 1endset @strSql='select top '+str(@PageSize)+' * from ' + @tbName + 'where id>(select max(id) from (select top '+str((@PageIndex-1)*@PageSize)+' id from ' + @tbName + ''+@strOrder+')a)'+@strOrder+''exec sp_executesql @strSqlCount,N'@TotalCout int output',@Total outputexec(@strSql)

调用:

declare @count int--exec [dbo].[spSqlPageByRownumber]'pagetest','*',50,20,'','order by id asc',@count outputexec [dbo].[spSqlPageByMaxTop]'pagetest','*',50,20,'','order by id asc',@count outputselect @count

上述内容就是sql中怎么实现分页查询,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

字段 查询 写法 条件 排序 测试 效率 数据 语句 尺寸 页码 内容 升序 变体 就是 序号 总数 感觉 技能 环境 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 简述设置服务器级字符集的方法 数据库安全网关厂商 网络技术项目计划书 服务器安全组什么 蓝汛网络安全等级新闻 光遇官方服务器在哪 国家网络安全知识视频 网络ftp服务器 使用管理服务器注册失败 神州数据库默认密码 数据库服务器维保 怀旧服服务器大战 mac恢复出厂后安装服务器损坏 中学生网络安全调查问卷答案 我的世界服务器如何当管理员 全椒自动化软件开发技术代理商 数据通信与网络技术实验报告 等保网络安全产品清单下载 电话未接通显示无法连接到服务器 黄浦区网络技术咨询销售方法 林权类数据库建设 湖北省网络安全知识大赛 嘉定区信息软件开发定制平均价格 朝阳回收服务器报价单 青岛软件开发怎么做 郑州web前端软件开发服务 南宁加固服务器价格多少 为什么用友通连接不上服务器 数据库原理总结报告心得体会 手机总显示服务器安全证书怎么办
0