分页存储过程(三)在sqlserver中打造更加准确的分页结果

有人提出游标不好,会锁定行,幸亏我锁定的是临时表,不是数据表,不影响数据表的写操作。

下面是14楼的回复,让我茅塞顿开,于是有了今天的改进版,取消了游标的使用,临时表还是存在的,谢谢。

其实你只要分成两次查询即可:

1, 还是用row_number查主表分页

2, row_number查主表分页 inner join 明细表..用不到游标的.

复制代码 代码如下:

–不用游标的分页

–先将分页的主表放在临时表中,然后用临时表和子表联合查询,来获取子表信息

–既保证了分页的正确性,也包括了子表信息

create table #order

(

number bigint,

orderseqno varchar(36),

)

insert into #order

select * from (select row_number() over (order by oi.createdate desc) as rownumber,oi.orderseqno

from orderinfo oi where oi.orderseqno like ‘%2%’ ) as o

where o.rownumber between 10 and 20

select * from #order inner join orderdetail od on od.orderseqno=#order.orderseqno

drop table #order


复制代码 代码如下:

–select top 10 oi.orderseqno, oi.goodsname ,ci.companyname,od.*

–from orderinfo oi inner join companyinfo ci on oi.companyid=ci.companyid

–left join orderdetail od on oi.orderseqno=od.orderseqno

–使用row_unmber()实现分页

–本来我们想要的结果是10条订单,结果却不是10条订单,而是10条明细

–其实是针对的子表进行分页了,订单并不是要显示的个数,出来的个数是明细的个数

–就是因为主表和子表联合查询的结果,主表记录和子表记录是1:n的关系,一个主表记录有多个明细

–建立聚集索引

— clustered index index_orderinfo on orderinfo (orderseqno)

–显示查询执行计划

–set statistics io on

select * from

(select row_number () over (order by oi.createdate desc) as rownumber,oi.orderseqno ,od.orderdetailid

from orderinfo oi left join orderdetail od on oi.orderseqno=od.orderseqno

where oi.orderseqno like ‘%2%’

) as o

where rownumber between 10 and 20

–不用游标的分页

–先将分页的主表放在临时表中,然后用临时表和子表联合查询,来获取子表信息

–既保证了分页的正确性,也包括了子表信息

create table #order

(

number bigint,

orderseqno varchar(36),

)

insert into #order

select * from (select row_number() over (order by oi.createdate desc) as rownumber,oi.orderseqno

from orderinfo oi where oi.orderseqno like ‘%2%’ ) as o

where o.rownumber between 10 and 20

select * from #order inner join orderdetail od on od.orderseqno=#order.orderseqno

drop table #order

–解决上面的问题,有以下几种办法

–1、先根据条件查询主表记录,然后在c#代码中循环,再次到数据库查询每条主表记录的明细信息,然后赋值给属性

–2、在数据库的存储过程中使用游标,也是先查询主表记录,然后使用游标循环的过程中,查询子表信息,然后在c#中

–集中处理

–很显然,后一种减少了数据库的往来开销,一次获取了想要的数据,个人认为要比第一种好,欢迎大家一起讨论更好的办法

–需要注意的就是row_number()返回的类型是bigint,而不是int

–下面是游标的存储过程

–建立主表临时表

create table #temp

(

rownumber bigint,

orderseqno varchar(36),

goodsname varchar(50),

companyname varchar(100)

)

–建立子表临时表

create table #detail

(

orderseqno varchar(36),

detailid uniqueidentifier,

unitprice decimal(12,2),

qty int

)

–插入主表数据到主表临时表

insert into #temp

select *

–oo.rownumber, oo.orderseqno, oo.goodsname, oo.companyname

from

(select row_number () over (order by oi.createdate desc) as rownumber,

oi.orderseqno, oi.goodsname ,ci.companyname

from orderinfo oi inner join companyinfo ci on oi.companyid=ci.companyid

where oi.createdate<getdate()

) as oo

where rownumber between 10 and 20

–定义游标

declare @temp_cursor cursor

–给游标赋值

set @temp_cursor=cursor for select #temp.orderseqno,#temp.goodsname from #temp

–定义游标循环过程中所需保存的临时数据

declare @orderseqno varchar(36),@goodsname varchar(50)

–打开游标

open @temp_cursor

fetch next from @temp_cursor into @orderseqno,@goodsname

–循环游标,查询子表数据,然后插入子表临时表

while @@fetch_status=0

begin

insert into #detail

select od.orderseqno,od.orderdetailid, od.unitprice,od.qty

from orderdetail od

where od.orderseqno=@orderseqno

fetch next from @temp_cursor into @orderseqno,@goodsname

end

–关闭游标

close @temp_cursor

deallocate @temp_cursor

select * from #temp

select * from #detail

–删除临时表

drop table #temp

drop table #detail

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐