bestlong 怕失憶論壇

 

 

搜索
查看: 8826|回復: 4
go

MSSQL 分頁處理 [複製鏈接]

Rank: 9Rank: 9Rank: 9

1#
發表於 2010-2-25 13:51 |只看該作者 |倒序瀏覽 |打印
分頁的技巧有兩種,一種是直接透過 T-SQL,另一種是透過 Store Procedure

假設 Northwind 有一個 Customer的 Table,你需要取回 41~50 筆的記錄,T-SQL語法該如何作呢?

T-SQL:
  1. Select Top 10 CustomerID,CompanyName,ContactName,Country
  2. from Customers
  3. where CustomerID Not in (Select top 40 CustomerID from Customers order by Country,CustomerID)
  4. Order by Country,CustomerID
複製代碼
Store Procedure:
  1. CREATE PROCEDURE northwind_OrdersPaged
  2. (
  3.   @PageIndex int,
  4.   @PageSize int
  5. )
  6. AS
  7. BEGIN
  8. DECLARE @PageLowerBound int
  9. DECLARE @PageUpperBound int
  10. DECLARE @RowsToReturn int

  11. -- First set the rowcount
  12. SET @RowsToReturn = @PageSize * (@PageIndex + 1)
  13. SET ROWCOUNT @RowsToReturn

  14. -- Set the page bounds
  15. SET @PageLowerBound = @PageSize * @PageIndex
  16. SET @PageUpperBound = @PageLowerBound + @PageSize + 1

  17. -- Create a temp table to store the select results
  18. CREATE TABLE #PageIndex
  19. (
  20.   IndexId int IDENTITY (1, 1) NOT NULL,
  21.   OrderID int
  22. )

  23. -- Insert into the temp table
  24. INSERT INTO #PageIndex (OrderID)
  25. SELECT OrderID
  26. FROM Orders
  27. ORDER BY OrderID DESC

  28. -- Return total count
  29. SELECT COUNT(OrderID) FROM Orders

  30. -- Return paged results
  31. SELECT O.*
  32. FROM Orders O, #PageIndex PageIndex
  33. WHERE O.OrderID = PageIndex.OrderID
  34.   AND PageIndex.IndexID > @PageLowerBound
  35.   AND PageIndex.IndexID < @PageUpperBound
  36. ORDER BY PageIndex.IndexID
  37. END
複製代碼
資料參考 http://blog.sina.com.tw/4907/art ... 07&entryid=3921
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

2#
發表於 2010-2-25 14:10 |只看該作者
SQL Server 2000 Paging and Sorting Using ROWCOUNT and SQL_VARIANT
http://www.codeproject.com/KB/da ... KPagingSorting.aspx
  1. CREATE PROCEDURE dbo.up_GetSortedSalesOrdersByPageUsingRowset
  2.     @orderedOnStart datetime,
  3.     @orderedOnEnd datetime,
  4.     @pageNumber int,
  5.     @pageSize int,
  6.     @sortExpression varchar(100),
  7.     @sortOrder varchar(4),
  8.     @virtualCount int OUTPUT
  9. AS

  10.     /*
  11.         Make sure that the page number is at least 1
  12.     */
  13.     IF @pageNumber < 1
  14.     BEGIN
  15.         SET @pageNumber = 1
  16.     END

  17.     SELECT
  18.         @virtualCount = COUNT(*)
  19.     FROM
  20.         Sales.SalesOrderHeader Header
  21.     WHERE
  22.         Header.[OrderDate] >= @orderedOnStart
  23.         AND Header.[OrderDate] < @orderedOnEnd

  24.     DECLARE @lastKeyValue numeric(18,0)
  25.     DECLARE @lastAscendingSortValue SQL_Variant
  26.     DECLARE @lastDescendingSortValue SQL_Variant

  27.     DECLARE @numberToIgnore int

  28.     SET @numberToIgnore = (@pageNumber-1) * @pageSize

  29.     IF @numberToIgnore > 0
  30.     BEGIN
  31.         /*
  32.         Get the last available sort data and unique key
  33.         value from the last page.
  34.         */
  35.         SET ROWCOUNT @numberToIgnore

  36.         SELECT
  37.             @lastKeyValue = [UniqueValue],
  38.             @lastAscendingSortValue = [AscendingSort],
  39.             @lastDescendingSortValue = [DescendingSort]
  40.         FROM
  41.         (
  42.             SELECT
  43.                 Header.[SalesOrderID] AS [UniqueValue],
  44.                 CASE
  45.                     WHEN
  46.                         UPPER(@sortOrder) = 'DESC'
  47.                         AND UPPER(@sortExpression) = 'CUSTOMERID'
  48.                     THEN
  49.                         CONVERT(SQL_Variant, [CustomerID])
  50.                     WHEN
  51.                         UPPER(@sortOrder) = 'DESC'
  52.                         AND UPPER(@sortExpression) = 'TOTALDUE'
  53.                     THEN
  54.                         CONVERT(SQL_Variant, [TotalDue])
  55.                     WHEN
  56.                         UPPER(@sortOrder) = 'DESC'
  57.                         AND UPPER(@sortExpression) = 'ORDERDATE'
  58.                     THEN
  59.                         CONVERT(SQL_Variant, [OrderDate])
  60.                     ELSE
  61.                         NULL
  62.                 END AS [DescendingSort],
  63.                 CASE
  64.                     WHEN
  65.                         UPPER(@sortOrder) = 'ASC'
  66.                         AND UPPER(@sortExpression) = 'CUSTOMERID'
  67.                     THEN
  68.                         CONVERT(SQL_Variant, [CustomerID])
  69.                     WHEN
  70.                         UPPER(@sortOrder) = 'ASC'
  71.                         AND UPPER(@sortExpression) = 'TOTALDUE'
  72.                     THEN
  73.                         CONVERT(SQL_Variant, [TotalDue])
  74.                     WHEN
  75.                         UPPER(@sortOrder) = 'ASC'
  76.                         AND UPPER(@sortExpression) = 'ORDERDATE'
  77.                     THEN
  78.                         CONVERT(SQL_Variant, [OrderDate])
  79.                     ELSE
  80.                         NULL
  81.                 END AS [AscendingSort]
  82.             FROM
  83.                 Sales.SalesOrderHeader Header
  84.             WHERE
  85.                 Header.[OrderDate] >= @orderedOnStart
  86.                 AND Header.[OrderDate] < @orderedOnEnd
  87.             ) AS Derived
  88.         ORDER BY
  89.             [AscendingSort] ASC,
  90.             [DescendingSort] DESC,
  91.             [UniqueValue] ASC
  92.     END

  93.     /*
  94.     Select the first @pageSize records that come after the last sort
  95.     data/unique value from the last page. If this is the first page,
  96.     just get the first @pageSize records.
  97.     */

  98.     SET ROWCOUNT @pageSize

  99.     SELECT
  100.         [SalesOrderID],
  101.         [OrderDate],
  102.         [TotalDue],
  103.         [CustomerID]
  104.     FROM
  105.     (
  106.         SELECT
  107.             [SalesOrderID],
  108.             [OrderDate],
  109.             [TotalDue],
  110.             [CustomerID],
  111.             [SalesOrderID] As [UniqueValue],
  112.             CASE
  113.                 WHEN
  114.                     UPPER(@sortOrder) = 'DESC'
  115.                     AND UPPER(@sortExpression) = 'CUSTOMERID'
  116.                 THEN
  117.                     CONVERT(SQL_Variant, [CustomerID])
  118.                 WHEN
  119.                     UPPER(@sortOrder) = 'DESC'
  120.                     AND UPPER(@sortExpression) = 'TOTALDUE'
  121.                 THEN
  122.                     CONVERT(SQL_Variant, [TotalDue])
  123.                 WHEN
  124.                     UPPER(@sortOrder) = 'DESC'
  125.                     AND UPPER(@sortExpression) = 'ORDERDATE'
  126.                 THEN
  127.                     CONVERT(SQL_Variant, [OrderDate])
  128.                 ELSE
  129.                     NULL
  130.             END AS [DescendingSort],
  131.             CASE
  132.                 WHEN
  133.                     UPPER(@sortOrder) = 'ASC'
  134.                     AND UPPER(@sortExpression) = 'CUSTOMERID'
  135.                 THEN
  136.                     CONVERT(SQL_Variant, [CustomerID])
  137.                 WHEN
  138.                     UPPER(@sortOrder) = 'ASC'
  139.                     AND UPPER(@sortExpression) = 'TOTALDUE'
  140.                 THEN
  141.                     CONVERT(SQL_Variant, [TotalDue])
  142.                 WHEN
  143.                     UPPER(@sortOrder) = 'ASC'
  144.                     AND UPPER(@sortExpression) = 'ORDERDATE'
  145.                 THEN
  146.                     CONVERT(SQL_Variant, [OrderDate])
  147.                 ELSE
  148.                     NULL
  149.             END AS [AscendingSort]
  150.         FROM
  151.             Sales.SalesOrderHeader Header
  152.         WHERE
  153.             Header.[OrderDate] >= @orderedOnStart
  154.             AND Header.[OrderDate] < @orderedOnEnd
  155.     ) Derived
  156.     WHERE
  157.     (
  158.         @lastAscendingSortValue IS NULL
  159.         AND @lastDescendingSortValue IS NULL
  160.         AND @lastKeyValue IS NULL
  161.     )
  162.     OR
  163.     (
  164.         (@lastAscendingSortValue IS NOT NULL)
  165.         AND
  166.         (
  167.             ([AscendingSort] > @lastAscendingSortValue)
  168.             OR
  169.             (
  170.                 [AscendingSort] = @lastAscendingSortValue
  171.                 AND [UniqueValue] > @lastKeyValue
  172.             )
  173.         )
  174.     )
  175.     OR
  176.     (
  177.         (@lastDescendingSortValue IS NOT NULL)
  178.         AND
  179.         (
  180.             ([DescendingSort] < @lastDescendingSortValue)
  181.             OR
  182.             (
  183.                 [DescendingSort] = @lastDescendingSortValue
  184.                 AND [UniqueValue] > @lastKeyValue
  185.             )
  186.         )
  187.     )
  188.     ORDER BY
  189.         [AscendingSort] ASC,
  190.         [DescendingSort] DESC,
  191.         [SalesOrderID] ASC

  192.     SET ROWCOUNT 0
  193. GO
複製代碼
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

3#
發表於 2010-2-25 14:12 |只看該作者
  1. --有排序,又稱【夾擠式分頁查詢】。MS-SQL 2000,常見的分頁用語法。
  2. SELECT * FROM
  3. (
  4.     SELECT TOP [每頁長度] * FROM
  5.     (
  6.         SELECT TOP [每頁長度*第幾頁] [欄位1, 欄位2, ...]
  7.         FROM [資料表]
  8.         WHERE [篩選條件]     
  9.         ORDER BY [排序欄位] [DESC/ASC]
  10.     )
  11.     AS [資料表别名1]
  12.     ORDER BY [排序欄位] [ASC/DESC]
  13. )
  14. AS [資料表别名2]
  15. ORDER BY [排序欄位] [DESC/ASC]
複製代碼
  1. --MS-SQL 2005以後才有RANK()語法
  2. SELECT * FROM
  3. (
  4.     SELECT rank() OVER ( ORDER BY [排序欄位] [ASC/DESC] ) AS RankNumber, * FROM
  5.     (
  6.         SELECT [欄位1, 欄位2, ...]
  7.         FROM [資料表]
  8.         WHERE [篩選條件]     
  9.     )
  10.     AS [資料表别名1]
  11. ) AS [資料表别名2]
  12. WHERE RankNumber between [每頁長度*(第幾頁-1)] and [每頁長度*第幾頁]
複製代碼
資料參考 http://www.player.idv.tw/prog/index.php?title=SQL#MS-SQL
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

4#
發表於 2010-2-25 14:29 |只看該作者
  1. ALTER PROCEDURE [dbo].[sp_page_test]
  2. @rows_per_page int,
  3. @current_page int
  4. AS
  5. DECLARE @start_row_num int
  6. BEGIN
  7. SET @start_row_num = (@current_page) * @rows_per_page --設定從第幾個record開始讀
  8. WITH t AS
  9. (
  10. SELECT ROW_NUMBER() OVER(ORDER BY DOCUMENT_ID) AS row_number, DOCUMENT_ID, DOCUMENT_NAME
  11. FROM DM_DOCUMENT
  12. ) --加入ROW_NUMBER()模擬成另一個table
  13. SELECT * FROM t
  14. WHERE row_number BETWEEN @start_row_num + 1 AND @start_row_num + @rows_per_page --執行分頁
  15. END
複製代碼
資料參考 http://blog.blueshop.com.tw/blac ... 07/01/06/49123.aspx
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

5#
發表於 2010-5-14 15:58 |只看該作者
這個方式會傳回多個結果集, 不過卻可以通用, 只要傳入 SQL 指令即可用 exec PagingRecordSet @strSQL='select A=1' 就可以了解
但是這樣 SQL 命令就需要自己處理 SQL Injection 的問題
  1. CREATE PROCEDURE PagingRecordSet
  2. --  @strSQL VarChar(1000),  --查詢sql,如select * from [user]
  3. --  @strSQL NVarChar(1000),  --查詢sql,如select * from [user]
  4.   @strSQL text,         --查詢sql,如select * from [user]
  5.   @PageIndex int = 1,   --查詢的頁號
  6.   @PageSize int = 30    --每頁顯示紀錄數
  7. AS
  8.   set nocount on
  9.   declare @p1 int
  10.   declare @currentPage int
  11.   set @currentPage = 0
  12.   declare @RowCount int
  13.   set @RowCount = 0
  14.   declare @PageCount int
  15.   set @PageCount = 0
  16.   
  17.   exec sp_cursoropen @p1 output, @strSQL, @scrollopt = 1, @ccopt = 1, @RowCount = @RowCount output --得到總紀錄數
  18.   select @PageCount = ceiling(1.0 * @RowCount / @PageSize) --得到總頁數
  19.         ,@CurrentPage = (@PageIndex - 1) * @PageSize + 1   

  20.   select @RowCount, @PageCount --顯示總紀錄數,總頁數
  21.   exec sp_cursorfetch @p1, 16, @CurrentPage, @PageSize
  22.   exec sp_cursorclose @p1

  23.   set nocount off
  24. GO
複製代碼
此方式簡化了程式的複雜度, 但在巨量資料環境下效能就差很多
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw
‹ 上一主題|下一主題

Archiver|怕失憶論壇

GMT+8, 2024-4-24 20:37 , Processed in 0.010751 second(s), 11 queries .

Powered by Discuz! X1.5

© 2001-2010 Comsenz Inc.