当前位置: 代码网 > it编程>数据库>MsSqlserver > SQL Server中获取指定范围分页取数的两种方式

SQL Server中获取指定范围分页取数的两种方式

2025年12月21日 MsSqlserver 我要评论
引言在 sql server 中获取指定范围的记录(分页/分批取数),核心依赖 offset/fetch(sql server 2012+ 推荐)和 row_number() 函数(兼容低版本),以下

引言

在 sql server 中获取指定范围的记录(分页/分批取数),核心依赖 offset/fetch(sql server 2012+ 推荐)和 row_number() 函数(兼容低版本),以下是两种主流方式的详细实现,结合 fdquery 适配场景说明:

一、推荐方式:offset/fetch(sql server 2012+)

语法简洁、性能优,是官方推荐的分页语法,适配 fdquery 分批取数场景。

基础语法

select 字段列表 
from 表名 
order by 排序字段 -- 必须指定 order by,否则offset/fetch 无效
offset 偏移量 rows -- 跳过前 n 行(偏移量 = (页码-1)*每页行数)
fetch next 行数 rows only; -- 取后续 n 行

示例1:基础分页(适配 fdquery 手动分批)

// delphi + fdquery 示例:加载第3页,每页20行
procedure tform1.loadsqlserverpage(pageindex: integer; pagesize: integer);
var
  offsetnum: integer;
begin
  offsetnum := (pageindex - 1) * pagesize; // 计算偏移量(第1页偏移0,第2页偏移20...)
  
  fdquery1.close;
  fdquery1.sql.clear;
  fdquery1.sql.text := format(
    'select id, name, class_id, grade ' +
    'from t_student ' +
    'order by id ' + // 必须排序,建议用主键/索引字段
    'offset %d rows ' +
    'fetch next %d rows only',
    [offsetnum, pagesize]
  );
  fdquery1.open;
end;

// 调用:加载第3页,每页20行
loadsqlserverpage(3, 20);

示例2:取前 n 行(简化版)

若仅需取前100行,可省略 offset:

select top 100 id, name from t_student order by id;
-- 等价于
select id, name from t_student order by id offset 0 rows fetch next 100 rows only;

二、兼容低版本:row_number() 函数(sql server 2005+)

若需兼容 sql server 2005/2008 等低版本,用 row_number() 生成行号,再筛选行号范围。

基础语法

select top 100 id, name from t_student order by id;
-- 等价于
select id, name from t_student order by id offset 0 rows fetch next 100 rows only;

示例:适配 fdquery 分批取数

procedure tform1.loadsqlserverbyrownum(pageindex: integer; pagesize: integer);
var
  startrow, endrow: integer;
begin
  startrow := (pageindex - 1) * pagesize + 1; // 起始行号(第1页:1,第2页:21...)
  endrow := pageindex * pagesize; // 结束行号(第1页:20,第2页:40...)
  
  fdquery1.close;
  fdquery1.sql.clear;
  fdquery1.sql.text := format(
    'select id, name, class_id, grade from (' +
    '  select ' +
    '    id, name, class_id, grade, ' +
    '    row_number() over (order by id) as rownum ' +
    '  from t_student ' +
    ') as temp ' +
    'where temp.rownum between %d and %d',
    [startrow, endrow]
  );
  fdquery1.open;
end;

// 调用:加载第2页,每页15行
loadsqlserverbyrownum(2, 15);

三、关键注意事项(适配 fdquery 场景)

必须排序:offset/fetch 和 row_number() 都依赖 order by,否则行号/偏移量无意义,建议用主键(如 id)或索引字段排序,提升性能;

性能优化

  1. 给排序字段加索引(如 create index idx_student_id on t_student(id));
  2. 避免 select *,仅查询需要的字段,减少数据传输;

边界处理:若偏移量超过总记录数,查询返回空结果,可先查总记录数再判断:

-- 查总记录数(适配 fdquery 统计总数) 
select count(*) from t_student where grade = '2025级';

fdquery 分批适配

  1. 若用「自动分批」(fetchoptions.rowsetsize),fdquery 会自动拼接 offset/fetch 语法(无需手动写分页);
  2. 若用「手动分页控件」,优先用 offset/fetch 语法(代码更简洁)。

四、对比:两种方式的适用场景

方式优点缺点适用版本
offset/fetch语法简洁、性能优仅支持 sql server 2012+2012 及以上
row_number()兼容低版本嵌套查询,语法稍复杂2005 及以上

五、fdquery 自动分批适配(无需手动写分页)

若无需手动控制页码,仅需“滚动加载”分批取数,可直接配置 fdquery 的 fetchoptions,firedac 会自动适配 sql server 的分批语法:

procedure tform1.fdqueryautobatch;
begin
  fdquery1.close;
  fdquery1.sql.text := 'select id, name, class_id from t_student order by id';
  
  with fdquery1.fetchoptions do
  begin
    mode := fmall; // 按需加载
    rowsetsize := 50; // 每批加载50行
    autofetchall := false; // 禁止一次性加载全量
  end;
  
  fdquery1.open; // 首次加载50行,滚动到底部自动加载下一批
end;

如果需要结合“多表关联查询+分页”“带条件筛选的范围取数”等场景,可补充具体需求,我会给出针对性示例。

以上就是sql server中获取指定范围分页取数的两种方式的详细内容,更多关于sql server指定范围分页取数的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com