2009年3月31日星期二

sybase分页查询思路

CREATE PROCEDURE GetDataByPage(
@SqlStr varchar(8000),
@PageSize int,
@CurrentPage int)
AS
DECLARE @FirstRec int, @LastRec int,@dt varchar(10)
BEGIN

SELECT @FirstRec = (@CurrentPage - 1) * @PageSize
SELECT @LastRec = (@CurrentPage * @PageSize + 1)

SELECT @dt= substring(convert(varchar,rand()),3,10)

SELECT @SqlStr = stuff(@SqlStr,charindex(' FROM ',upper(@SqlStr)),6,' INTO tempdb..Paging'+@dt+' FROM ')
EXECUTE (@SqlStr)

SELECT @SqlStr = 'ALTER TABLE tempdb..Paging'+@dt+' ADD RID numeric(10) IDENTITY PRIMARY KEY'
EXECUTE (@SqlStr)

SELECT @SqlStr = 'SELECT Count(*) From tempdb..Paging'+@dt
EXECUTE (@SqlStr)

SELECT @SqlStr = 'SELECT * FROM tempdb..Paging'+@dt+' WHERE RID >; '+convert(varchar,@FirstRec)+' and RID < '+convert(varchar,@LastRec)
EXECUTE (@SqlStr)

SELECT @SqlStr = 'DROP TABLE tempdb..Paging'+@dt
EXECUTE (@SqlStr)

END


另外一个小数据量时的简便方法:
select rowid=identity(12), * into #temptable1 from salesdetail
select * from #temptable1 where rowid<10>=1
注:当大数据量时将全表数据复制到临时表中是效率低下的

sybase中的临时表当用select into #table的形式时,是不记录日志的。速度非常快。
这点和oracle不同。算是sybase的一个feature.

用游标更好一些。
用临时表算法的空间复杂度是O(n),如果表很大或没有预存在Cache中,所用的I/O时间就非常可观了。
用游标定位到指定的页,空间复杂度应该是O(1),虽然游标遍历记录比直接用Select稍慢一点,但考虑到分页应用中,每次只读取一页的内容,所以这个时间性能上的损失可以忽略。


set rowcount 20
select * from salesdetail
set rowcount 0
注:此种方式不能设定查询的条件,如起始和结束位置、不能first、top、start at等。

一个简单的分页的存储过程:
create procedure test_p @ipage int, @num int as /* @ipage 页码, @num 每页的记录数 */
begin
declare @maxpages int, @rcount int /* @maxpages 最大页码 */
if @ipage>=100
select @maxpages=ceiling(count(*)/@num) from test
else
select @maxpages=100000
if @ipage<=@maxpages/2
begin
select @rcount=@ipage*@num
set rowcount @rcount
select id=identity(12),name,descs,ddd into #temptable1 from test order by id
select * from #temptable1 where id>(@ipage-1)*@num and id<= @ipage*@num
end else
begin
select @rcount=(@maxpages-@ipage+1)*@num
set rowcount @rcount
select id=identity(12),name,descs,ddd into #temptable2 from test order by id desc
select id,name, ddd,descs from #temptable2 where id>(@maxpages-@ipage)*@num and id<= (@maxpages-@ipage+1)*@num order by id desc
end
end

此存储过程的问题是:select into #temptable1需要大量的数据空间(tempdb),同时也会增加时间。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
版本更新:1.0.2
注意程序最后要加上set rowcount 0

create procedure splitpage @qry varchar(16384),@ipage int, @num int,@maxpages int = 5000 as
/*@qry SQL语句, @ipage 页数, @num 每页记录条数, @maxpages 最大查询页数 */
begin

declare @rcount int
declare @execsql varchar(16384)

if @ipage > @maxpages
begin
select '输入页数[' || convert(varchar,@ipage) || ']大于最大查询页数[' || convert (varchar,@maxpages) ||']'
return
end

select @rcount=@ipage*@num
set rowcount @rcount
set @execsql = stuff(@qry,charindex('select',@qry),6,'select sybid=identity(12),')
set @execsql = stuff(@execsql, charindex('from',@execsql),4,'into #temptable1 from')
set @execsql = @execsql || ' select * from #temptable1 where sybid>' || convert(varchar,(@ipage-1)*@num) || ' and sybid <= ' || convert(varchar,@ipage*@num)
execute (@execsql)
set rowcount 0
end

2009年3月12日星期四

网络小说推荐

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. 杯雪