加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

SQLServer2005 分页程序

发布时间:2020-12-12 15:58:33 所属栏目:MsSql教程 来源:网络整理
导读:method one set ?ANSI_NULLS? ON set ?QUOTED_IDENTIFIER? ON go ALTER ? PROCEDURE ? [ dbo ] . [ DividePage ] ?? @tabname ? nvarchar ( 2000 ), -- 要查询表名 ?? @fidlelist ? nvarchar ( 1000 ), -- 要查询字段 ?? @wheresql ? nvarchar ( 1000 ), --

PageNumber

SaleID

Product

SaleDate

SalePrice

2

12

PoolTable

7/11/1908
0:00

640

2

15

PoolTable

8/11/1908
0:00

641

2

18

PoolTable

9/11/1908
0:00

658

就如你所看到的,程序执行后将会返回一页的数据,包含三条记录,而且返回的是第二页的数据集。

需要注意的一点

一般来说,有两种方法完成数据结果的分页:在数据库层实现和不在数据库层实现。可以在客户端实现分页,但是这样做的时候,所有的数据都会返回到客户端,而且在进行数据分析的时候就决定了页面数目。在早期版本的SQL Server中,可以在数据库层实现分页,但是需要临时表和表变量。如果上面的例子没有使用CTE来进行分页的话,分页程序就不会那么简单。之所以这么简单就是因为使用了ROW_NUMBER函数的强大功能。在以后的文章中,我将会大概介绍一下其它三种排列函数,并展示它们提供的一些灵活易用的函数功能。

DECLARE @i SMALLINT
SET @i = 1

WHILE (@i <=100)
BEGIN?????
????? INSERT INTO SalesHistory?????
????? (Product,SaleDate,SalePrice)?????
????? VALUES?????
('Computer',DATEADD(mm,@i,'3/11/1919'),DATEPART(ms,GETDATE()) + (@i + 57) )

????? INSERT INTO SalesHistory?????
????? (Product,SalePrice)?????
????? VALUES?????
('BigScreen','3/11/1927'),GETDATE()) + (@i + 13) )
?????
????? INSERT INTO SalesHistory?????
????? (Product,SalePrice)?????
????? VALUES?????
('PoolTable','3/11/1908'),GETDATE()) + (@i + 29) )
?????
????? SET @i = @i + 1
END

?

CREATE PROCEDURE usp_SalesRecords(????? @PageSize FLOAT,????? @TargetPage SMALLINT)ASBEGIN????? WITH Sales_CTE(PageNumber,SaleID,Product,SalePrice)????? AS????? (SELECT CEILING((ROW_NUMBER() OVER (ORDER BY SaleDate ASC))/@PageSize) AS PageNumber,SalePrice FROM SalesHistory FROM SalesHistory????? )????? SELECT ??????????? PageNumber,SalePrice????? FROM ??????????? Sales_CTE????? WHERE ??????????? PageNumber = @TargetpageENDCREATE PROCEDURE usp_SalesRecords(????? @PageSize FLOAT,SalePrice????? FROM ??????????? Sales_CTE????? WHERE ??????????? PageNumber = @TargetpageEND

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

method one

set?ANSI_NULLS?ON

set?QUOTED_IDENTIFIER?ON

go




ALTER?PROCEDURE?[dbo].[DividePage]

??
@tabname?nvarchar(2000),--要查询表名

??@fidlelist?nvarchar(1000),--要查询字段

??@wheresql?nvarchar(1000),--查询条件

??@pk?nvarchar(20),--主键

??@order?nvarchar(100),--排序字段

??@pagenum?int,--要查询的页号

??@rowsum?int,--每页要显示的行数

??@allpage?int?output,--计算总页数

??@allrow?int?output--计算总行数

AS

??
declare?@sqlstr?nvarchar(4000),@tmpwhere?nvarchar(4000),@tmporder?nvarchar(100)

BEGIN

????
if(@order!='')

??????
begin

???????
set?@tmporder=@order

??????
end?

?????
else

???????
set?@tmporder=@pk;

????
set?@tmpwhere='';

????
if(@wheresql!='')

????
begin

???????
set?@tmpwhere='?where?'+@wheresql;

????
end

????
set?@sqlstr=N'select?*?from(select??'+@fidlelist+',?ROW_NUMBER()?OVER(order?by?'+@tmporder+')?as?row?from?'+@tabname+@tmpwhere+')?tmp?where?row?between?'+cast(((@pagenum-1)*@rowsum+1)?as?nvarchar)+'?and?'+cast(@pagenum*@rowsum?as?nvarchar);??

exec?sp_executesql?@sqlstr

????
set?@sqlstr=N'select?@allrow1?=count('+@pk+')?from?'+?@tabname+@tmpwhere

????
exec?sp_executesql?@sqlstr,N'@allrow1?int?OUTPUT',@allrow1=@allrow?output????

????
if(@allrow%@rowsum<>0)

????????
begin

??????????
set?@allpage=@allrow/@rowsum+1--获得总页数

????????end

????
else

??????????
set?@allpage=@allrow/@rowsum?----获得总页数


END?

?

method two:

SQL2005增加了不少新特性,其中NTILE和ROW_NUMER使得我们不再为SQL如何灵活方便的分页伤脑筋了(不必再羡慕Oracle等数据库了)。
  下面就是一个很简单的分页查询语句: DECLARE @rows_per_page AS INTEGER
DECLARE @current_page AS INTEGER
DECLARE @total_pages AS INTEGER

-- 设置每页的行数
SET @rows_per_page = 20
-- 设置要显示的页号(从1开始)
SET @current_page = 2
-- 计算总页数
SELECT @total_pages = COUNT(*) / @rows_per_page
FROM testtable;

-- 列出指定页的内容
WITH t AS
(
? SELECT NTILE(@total_pages) OVER(ORDER BY id) AS page_number,*
? FROM testtable
)
SELECT * from t
WHERE page_number = @current_page   程序简单到可以不用说明的程度。
  我们可以利用上述简单的语句,变化排序条件和查询表,就可以做出一个很通用的分页查询的存储过程或查询语句了。

  同样的,使用ROW_NUMBER也可以做到分页查询: DECLARE @rows_per_page AS INTEGER
DECLARE @current_page AS INTEGER
DECLARE @start_row_num AS INTEGER

-- 设置每页的行数
SET @rows_per_page = 20
-- 设置要显示的页号(从1开始)
SET @current_page = 2
-- 设置开始行号
SET @start_row_num = (@current_page - 1) * @rows_per_page

WITH t AS
(
? SELECT ROW_NUMBER() OVER(ORDER BY id) AS row_number,*
? FROM testtable
)
SELECT * from t
WHERE row_number BETWEEN @start_row_num AND @start_row_num + @rows_per_page  似乎更简单的样子。

?

method three:

先来一段代码:
WITH OrderedOrders AS
(SELECT *,
ROW_NUMBER() OVER (order by [id])as RowNumber  --id是用来排序的列
FROM table_info ) --table_info是表名
SELECT *
FROM OrderedOrders
WHERE RowNumber between 50 and 60;

在windows server 2003,sql server 2005 CTP,P4 2.66GHZ,1GB 内存下测试,执行时间0秒

,表中数据量230万

接下来大批量的数据查询性能瓶颈就在count了,不知道sql server 2005在这方面有没有什么改进.

附另一种方法:
SELECT *
FROM (select *,ROW_NUMBER() Over(order by id) as rowNum from table_info ) as myTable
where rowNum between 50 and 60;

method four:

CREATE PROCEDURE [dbo].[getPage]
?@pageSize??int,?????--页尺寸
?@currentPage?int = 1,????--当前页
?@fields???varchar(2000) = '*',?--返回的字段
?@tablename??varchar(200),???--表名
?@orderString?varchar(1000),???--排序字符串
?@whereString?varchar(1000)???--条件字符串
AS
BEGIN
?DECLARE @sql varchar(2000)
?DECLARE @strOrder?varchar(2000)
?DECLARE @strWhere?varchar(2000)

?set @strOrder = REPLACE(RTRIM(LTRIM(@orderString)),'order by','')
?if @strOrder != ''
??set @strOrder = ' order by ' + @strOrder
?else
??set @strOrder = ' order by ID DESC'

?set @strWhere = REPLACE(RTRIM(LTRIM(@whereString)),'where','')
?if @strWhere != ''
??set @strWhere = ' where ' + @strWhere

?if @pageSize = 0
??set @sql = 'select ' + @fields + ' from ' + @tablename + @strWhere + @strOrder
?else
??if @currentPage = 1
???set @sql = 'select top(' + Str(@pageSize) + ') ' + @fields + ' from ' + @tablename + @strWhere + @strOrder
??else
???begin
????set @sql = 'select top(' + Str(@pageSize) + ') * from (select top(' + Str(@pageSize * @currentPage) + ') ' + @fields + ',ROW_NUMBER() OVER ('
????set @sql = @sql + @strOrder
????set @sql = @sql + ') As RowNumber From ' + @tablename
????set @sql = @sql + @strWhere
????set @sql = @sql + ') as t where t.RowNumber > ' + Str(@pageSize * (@currentPage - 1))
????set @sql = @sql + @strOrder
???end

?exec(@sql)
END

?

method five:

SQL?Server?2005分页存储过程?已测

SET?ANSI_NULLS?ON
GO
SET?QUOTED_IDENTIFIER?ON
GO
Create?Procedure?[dbo].[flyso_Page2005]?
?@TableName?varchar(50),????????--表名
?@Fields?varchar(5000)?=?'*',????--字段名(全部字段为*)
?@OrderField?varchar(5000),????????--排序字段(必须!支持多字段)
?@sqlWhere?varchar(5000)?=?Null,--条件语句(不用加where)
?@pageSize?int,????????????????????--每页多少条记录
?@pageIndex?int?=?1?,????????????--指定当前为第几页
?@TotalPage?int?output,????????????--返回总页数?
?@totalRecord?int?output
as
begin

????Begin?Tran?--开始事务

????Declare?@sql?nvarchar(4000);
????--Declare?@totalRecord?int?output;????

????--计算总记录数
?????????
????if?(@SqlWhere=''?or?@sqlWhere=NULL)
????????set?@sql?=?'select?@totalRecord?=?count(*)?from?'?+?@TableName
????else
????????set?@sql?=?'select?@totalRecord?=?count(*)?from?'?+?@TableName?+?'?where?'?+?@sqlWhere

????EXEC?sp_executesql?@sql,N'@totalRecord?int?OUTPUT',@totalRecord?OUTPUT--计算总记录数????????
????
????--计算总页数
????select?@TotalPage=CEILING((@totalRecord+0.0)/@PageSize)

????if?(@SqlWhere=''?or?@sqlWhere=NULL)
????????set?@sql?=?'Select?*?FROM?(select?ROW_NUMBER()?Over(order?by?'?+?@OrderField?+?')?as?rowId,'?+?@Fields?+?'?from?'?+?@TableName?
????else
????????set?@sql?=?'Select?*?FROM?(select?ROW_NUMBER()?Over(order?by?'?+?@OrderField?+?')?as?rowId,'?+?@Fields?+?'?from?'?+?@TableName?+?'?where?'?+?@SqlWhere????
????????
????
????--处理页数超出范围情况
????if?@PageIndex<=0?
????????Set?@pageIndex?=?1
????
????if?@pageIndex>@TotalPage
????????Set?@pageIndex?=?@TotalPage

?????--处理开始点和结束点
????Declare?@StartRecord?int
????Declare?@EndRecord?int
????
????set?@StartRecord?=?(@pageIndex-1)*@PageSize?+?1
????set?@EndRecord?=?@StartRecord?+?@pageSize?-?1

????--继续合成sql语句
????set?@Sql?=?@Sql?+?')?as?'?+?@TableName?+?'?where?rowId?between?'?+?Convert(varchar(50),@StartRecord)?+?'?and?'?+??Convert(varchar(50),@EndRecord)
????
????Exec(@Sql)
????---------------------------------------------------
????If?@@Error?<>?0
??????Begin
????????RollBack?Tran
????????Return?-1
??????End
?????Else
??????Begin
????????Commit?Tran
????????Return?@totalRecord?---返回记录总数
??????End????
end

method six:

如何实现SQL Server 2005快速web分页

分页,就是按照某种规则显示分组数据集,但是在SQL Server 中,分页并不是十分容易就能够实现。在过去,开发人员通常需要自己编写程序,使用临时表格来实现分页功能,或者将所有的数据结果集返回到客户端,在客户端进行分页操作。从开发人员或者DBA的角度来看,两种方法都不能令人满意。

随着SQL Server的发布,其中的一些排序函数使得开发人员编写数据分页程序变得更加简单和高效。这些新的排序函数提供了统计数据集的数目,对数据集归类,按照某种标准对数据集排序等功能。在这篇文章中,我将着重介绍新增加的ROW-NUMBER排序函数,它会根据你指定的分类标准将结果数据集进行分类,同时给数据集分配连续的页面。

一个分页的实例

我总是喜欢通过例子来介绍如何使用新技术,所以让我们来看看如何设计一个存储程序,使用ROW_NUMBER这一新函数来实现数据的自动分页。

首先,需要定义一些数据结构。我们定义一个SalesHistory表格,它包含的数据是我们在网上售出产品的销售记录。包括一些常见的销售信息,例如,所售产品、售出日期、产品售出价格等。下面的脚本就是创建这样的一个表格:

IF OBJECT_ID('SalesHistory','U') > 0
????? DROP TABLE SalesHistory

CREATE TABLE SalesHistory
(?????
????? SaleID INT IDENTITY(1,1),?????
????? Product VARCHAR(30),??????
????? SaleDate SMALLDATETIME,??????
????? SalePrice MONEY

)

运行列表A中的脚本则在上面创建的SalesHistory表中添加一些例子数据。

现在数据表中已经具有实例数据。接下来我们看看如何调用程序来实现数据的分页显示。列表B包含这个程序的脚本内容。这个程序含有两个参数:1.页面大小(给定页面要显示的数据记录数目)2.目标页面(返回该页的数据记录)。

如果你刚刚开始使用SQL Server,可能会不熟悉以“WITH”开头的声明语句。这条语句会调用SQL Server中的一个新属性,我们称之为common table expression(CTE),从本质上来说,我们可以将CTE看作是高版本的临时表。

分页的实质就是CTE中的TSQL语句。在下面的选择语句中,我使用了一个新的排序函数——ROW_NUMBER(这一函数很容易使用,你只需要给ROW_NUMBER函数提供一个域名作为参数,ROW_NUMBER会用它来进行分页)。随后,我使用@PageSize参数来划分每页的行数以及每页的最大行数值。

例如,假设现在有一个包含三条记录的数据集,并设计每页显示两条记录,那么头两条记录将会在第一页显示,因为每页的行数必须小于或者等于第一个变量值。第三条记录将会在第二页显示,因为每页的可显示最大行数值应该小于2但是又大于1。

可以使用下面的脚本调用存储程序:

EXECUTE usp_SalesRecords

@PageSize = 3,

@TargetPage = 2

执行程序后的返回结果如下:

    推荐文章
      热点阅读