風人園

          弱水三千,只取一瓢,便能解渴;佛法無邊,奉行一法,便能得益。
          隨筆 - 99, 文章 - 181, 評論 - 56, 引用 - 0
          數據加載中……

          Paging (MS SQL Server/Oracle)

          雖然 DataGrid 控件自己帶了一個分頁處理機制,但它是將符合查詢條件的所有記錄讀入內存,然后進行分頁顯示的。隨著符合條件的記錄數目增多,就會出現運行效率問題,或者至少是資源的利用率下降。

          下面的代碼示例都以下面的表結構為準:

           

            Articles 表 SQL Server 類型 Oracle 類型
          PK Id int (自增) number(9) (插入時在當前最大值上加1)
            Author nvarchar(10) nvarchar2(10)
            Title nvarchar(50) nvarchar2(50)
            PubTime datetime date

          SQL Server / Access 等微軟產品中,我們通常的自定義分頁有兩種思路:

          一種是以 ASP.NET Forum 為代表的、“臨時表”方法:即在存儲過程中建立一個臨時表,該臨時表包含一個序號字段(1,2,3,....)以及表的主鍵(其他能夠唯一確定一行記錄的字段也是可以的)字段。存儲過程可能如下:(編號 SS1)

          CREATE Procedure GetAllArticles_Paged
          (
          ???? @PageIndex int,
          ???? @PageSize int,
          ???? @TotalRecords out int,
          ???? @TotalPages out int
          )
          AS

          DECLARE @PageLowerBound int
          DECLARE @PageUpperBound int

          -- Set the page bounds
          SET @PageLowerBound = @PageSize * @PageIndex
          SET @PageUpperBound = @PageLowerBound + @PageSize + 1

          -- Create a temp table to store the select results
          CREATE TABLE #tmp
          (
          ???? RecNo int IDENTITY (1, 1) NOT NULL,
          ???? ArticleID int
          )

          INSERT INTO #tmp
          ???? SELECT [ID]
          ???? FROM Articles
          ???? ORDER BY PubTime DESC

          SELECT A.*
          FROM Articles A (nolock), #tmp T
          WHERE A.ID = T.ArticleID AND
          ???? T.RecNo > @PageLowerBound AND
          ???? T.RecNo < @PageUpperBound
          ORDER BY T.RecNo

          GO

          另一種可能更適合程序中“拼湊” SQL 語句:用兩次 TOP 命令取得我們所要的分頁數據,例如:(編號 SS2)

          SELECT * FROM
          ???? (
          ???? SELECT TOP(PageSize) * FROM
          ???? (
          ????????? SELECT TOP (PageSize * PageIndex) *
          ????????? FROM Articles
          ????????? ORDER BY PubTime DESC
          ???? )
          ???? ORDER BY PubTime ASC
          )
          ORDER BY PubTime DESC

          這個的想法就是“掐頭去尾”,還有不少分頁的方法,這里就不一一列出了。

          對于 Oracle 數據庫,有幾處不同嚴重妨礙了上面幾個方法的實施,比如,Oracle 不支持 TOP 關鍵字:不過這個好像并不十分嚴重,因為它提供了 rownum 這個隱式游標,可以實現與 TOP 類似的功能,如:

          SELECT TOP 10 ... FROM WHERE ...

          要寫成

          SELECT ... FROM ... WHERE ... AND rownum <= 10

          rownum 是記錄序號(1,2,3...),但有一個比較麻煩的事情是:如果 SQL 語句中有 ORDER BY ... 排序的時候,rownum 居然是先“標號”后排序!這樣,這個序號如果不加處理是不合乎使用需求的。

          至于臨時表,Oracle 的臨時表和 SQL Server 的有很大不同,我還沒搞懂這個東西,就不妄加揣測了。

          國內網站中介紹 Oracle 分頁的資料很少,我找到了一個國外站點(www.faqts.com)的一篇 FAQ,根據這篇文章的介紹,可以如下分頁:(編號 Ora1)

          SELECT * FROM
          ???? (
          ???? SELECT A.*, rownum r
          ???? FROM
          ????????? (
          ????????? SELECT *
          ????????? FROM Articles
          ????????? ORDER BY PubTime DESC

          ????????? ) A
          ???? WHERE rownum <= PageUpperBound
          ???? ) B
          WHERE r > PageLowerBound;

          其中藍色部分可以改為任意的、需要的 SQL SELECT 語句,這點倒是挺方便的。

           

          posted on 2007-02-12 15:57 風人園 閱讀(334) 評論(0)  編輯  收藏 所屬分類: Database

          主站蜘蛛池模板: 彭州市| 眉山市| 吴桥县| 泗洪县| 平陆县| 大足县| 澜沧| 永宁县| 西安市| 庆云县| 孟州市| 关岭| 临汾市| 望都县| 子洲县| 武鸣县| 东明县| 育儿| 科技| 禄劝| 贵定县| 河南省| 台北县| 遂宁市| 吕梁市| 河池市| 怀柔区| 民权县| 兴义市| 北辰区| 漳浦县| 祁东县| 沙湾县| 全椒县| 化州市| 佛山市| 苍梧县| 天峨县| 林州市| 宜春市| 旌德县|