有人提出游标不好,会锁定行,幸亏我锁定的是临时表,不是数据表,不影响数据表的写操作。
下面是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