版本12.5.2,分頁取資料的sql怎麼寫?(轉載)

zenzuguo發表於2006-12-13

版本12.5.2,分頁取資料的sql怎麼寫?

取第11條到第20條的記錄:
象mysql一樣,select * from table where c1='a' start 11 limit 10

set rowcount 20
-- get 20 rows
-- discard the first 10 rows
set rowcount 0

您可以使用 FIRST 或 TOP 關鍵字限制查詢的結果集中包括的行數。這些關鍵字用於包括 ORDER BY 子句的查詢。

示例
以下查詢返回在按姓氏對僱員進行排序時首先出現的僱員的資訊:

SELECT FIRST *
FROM employee
ORDER BY emp_lname
以下查詢返回按姓氏排序時出現的前五個僱員:

SELECT TOP 5 *
FROM employee
ORDER BY emp_lname
在使用 TOP 時,您也可以使用 START AT 來提供偏移。以下語句列出按姓氏以降序進行排序時出現的第五個和第六個僱員:

SELECT TOP 2 START AT 5 *
FROM employee
ORDER BY emp_lname DESC
FIRST 和 TOP 只能與 ORDER BY 子句聯合使用,以確保獲得一致的結果。如果使用 FIRST 或 TOP 時沒有 ORDER BY,則會觸發語法警告,並且很可能產生無法預知的結果。

注意
'start at' 值必須大於 0。當 'top' 為常量時,其值必須大於 0;當 'top' 為變數時,其值必須大於或等於 0。

SYBASE 不提供這種方式的提取,除非自己寫一個遊標

top 語句不行啊

1> select top 10 * from tblStudentCode order by Code
2> go
Msg 102, Level 15, State 1:
Server 'DBSVR', Line 1:
Incorrect syntax near '10'.

top語句在12.5.3之後才支援,實際上使用set rowcount n是個不錯的選擇

top在ASE 15可以支援,但不知道start at支不支援?

一段很好的分頁程式,速度很快,sybase內部員工寫的,改成自己需要的SQL吧。

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<
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

好事做到底,送個通用版吧

create procedure splitpage @qry varchar(16384),@ipage int, @num int as SQL語句, @ipage 頁數, @num 每頁記錄條數 */
begin
declare @maxpages int
declare @rcount int
declare @execsql varchar(16384)

if @ipage>=100
select @maxpages=ceiling(count(*)/@num) from test
else
select @maxpages=100000
if @ipage<
begin
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)

end else
begin
select @rcount=(@maxpages-@ipage+1)*@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 || ' order by sybid desc'
set @execsql = @execsql || ' select * from #temptable1 where sybid > ' || convert(varchar,(@maxpages-@ipage)*@num) || ' and sybid <= ' || convert(varchar,(@maxpages-@ipage+1)*@num)
execute (@execsql)
end
end


>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
我在專案中也是使用這個模式的,問題是寫臨時表時是否會發生物理寫操作?如果發生,還有沒有不需要寫臨時表的方案?

vc00, sybase中的臨時表當用select into #table的形式時,是不記錄日誌的。速度非常快。
這點和oracle不同。算是sybase的一個feature.

ncowboy ,老程式在處理10萬頁以上結果集會出現問題。用select @maxpages=ceiling(count(*)/@num) from test此處使用是不對的。
由於即席查詢時獲取maxpages效率不高,對此作以下修改:可以由使用者指定最大查詢頁數,預設定為5000

create procedure splitpage @qry varchar(16384),@ipage int, @num int,@maxpages int = 5000 as
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)
end

由於無法精確且高效取出即席查詢結果集的總頁數,原程式中考慮後幾頁查詢的最佳化演算法就無法使用了。
如果可以先算出精確的總頁數,然後作為引數傳給splitpage,那麼也可以把查詢後幾頁的演算法再補上。

誰有更好的辦法也可以提出來大家一起把這個分頁儲存過程最佳化到底。

版本更新:1.0.2
注意程式最後要加上set rowcount 0

create procedure splitpage @qry varchar(16384),@ipage int, @num int,@maxpages int = 5000 as
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

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/106285/viewspace-883679/,如需轉載,請註明出處,否則將追究法律責任。

相關文章