在编写分页存储过程前我们先为数据库创建一个测试表,这个测试表明叫做order,当中有3个字段,分别是or_id,orName,dateSta;下面创建表脚本:
CREATE TABLE [dbo].[Orders]( [or_id] [int] IDENTITY(1,1) NOT NULL, [orName] [nvarchar](50) NOT NULL, [dateSta] [datetime] NOT NULL, CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED ( [or_id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'写入时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Orders', @level2type=N'COLUMN',@level2name=N'dateSta' GO SET IDENTITY_INSERT [dbo].[Orders] ON INSERT [dbo].[Orders] ([or_id], [orName], [dateSta]) VALUES (1, N'naoqiu.com', CAST(0x0000A03700FEF029 AS DateTime)) INSERT [dbo].[Orders] ([or_id], [orName], [dateSta]) VALUES (2, N'naoqiu.com', CAST(0x0000A03700FF5BE8 AS DateTime)) INSERT [dbo].[Orders] ([or_id], [orName], [dateSta]) VALUES (3, N'押金', CAST(0x0000A03700FF5BF6 AS DateTime)) INSERT [dbo].[Orders] ([or_id], [orName], [dateSta]) VALUES (4, N'费用', CAST(0x0000A03700FF5BF6 AS DateTime)) INSERT [dbo].[Orders] ([or_id], [orName], [dateSta]) VALUES (5, N'http://naoqiu.com', CAST(0x0000A03700FF5BF6 AS DateTime)) SET IDENTITY_INSERT [dbo].[Orders] OFF /****** Object: Default [DF_Orders_dateSta] Script Date: 04/18/2012 15:31:11 ******/ ALTER TABLE [dbo].[Orders] ADD CONSTRAINT [DF_Orders_dateSta] DEFAULT (getdate()) FOR [dateSta] GO
现在我们先看在sql 2005上传统的分页存储过程:
Create Procedure [dbo].[prPageList] ( @PageSize int=20,/*每页行数*/ @PageIndex int=1,/*传进页数*/ @Field nvarchar(2000),/*查询字段*/ @QueryString nvarchar(3000),/*查询语句*/ @Orderby nvarchar(1000)/*排序字段*/ ) AS Set NoCount ON Declare @list_id1 int,@list_id2 int DECLARE @SqlQuery nvarchar(4000) Set @list_id2=(@PageSize*@PageIndex)--当前页记录结束 Set @list_id1=(@list_id2-@PageSize)--当前页记录开始 Set @SqlQuery=N'Select * From (Select ROW_NUMBER() Over(order by ' +@Orderby +N')AS list_id,' +@Field +' ' +@QueryString +N')AS A Where A.list_id>' +Cast(@list_id1 AS Nvarchar) +N' and A.list_id<=' +Cast(@list_id2 AS Nvarchar) print @SqlQuery Execute sp_executesql @SqlQuery Set @SqlQuery='Select count(*) '+@QueryString Execute sp_executesql @SqlQuery RETURN
调用示例:exec prPageList 10,100,'orderID','from orders','dateSta desc'
这种的编写有以下优点:
缺点:字符串超过4000该存储过程执行会发生异常;需要执行两次检索表,花费资源大;当选择第二页,还需要执行两次,一次是列表,一次是统计总数。
现在在同等情况下为了提高性能,提高语句执行效率。需要对以上的分页存储过程的逻辑思路进行个调整:
更具以上的思路,现在我直接把代码贴出来:
--综合公用分页存储过程
Create procedure [dbo].[Test_Common_PageList_TemTableByRelation] @pageIndex int,--当前页索引,第一页为:1 @pageSize int,--每页显示条数 @count int,--总数第一次传0 @id varchar(40),--主键id或关联字段 @sortparam varchar(50),--排序 @selectParam nvarchar(2000),--查询字段 @condition nvarchar(2000),--查询条件 @temTable nvarchar(3000),--临时表字符串 @dropTable varchar(300),--删除临时表字符串 @relation varchar(2000),--关联表 @insrtParam varchar(100),--插入到统计总量临时表的字段 @param varchar(100)--插入到页显示的临时表字段 as declare @sql nvarchar(4000),@min int,@max int,@date varchar(15),@tem1 varchar(20),@tem2 varchar(20),@part2 nvarchar(4000) set @date=replace(CONVERT(varchar,getdate(),114),':','') set @tem1='#page1'+@date set @tem2='#page2'+@date set @min=(@pageIndex-1)*@pageSize+1 set @max=@pageIndex*@pageSize set @sql=' select '+@id+' as spkid'+@insrtParam+',ROW_NUMBER() OVER (ORDER BY '+@sortparam+') AS RowNumber into '+@tem1+' from '+@condition+' select spkid,RowNumber'+@param+' into '+@tem2+' from '+@tem1+' where RowNumber between '+CAST(@min as varchar(11))+' and '+ CAST(@max as varchar(11)) if @count=0 begin set @part2='declare @count int set @count=(select max(RowNumber) from '+@tem1+') if @count is null set @count=0 select '+@selectParam+',@count as num' end else begin set @part2='select '+@selectParam+','+CAST(@count as varchar(11))+' as num' end set @part2=@part2+',RowNumber from '+@tem2+' as pt join '+@relation+' order by pt.RowNumber truncate table '+@tem1+' truncate table '+@tem2+' drop table '+@tem1+' drop table '+@tem2+' '+@dropTable --关闭影响行数 exec('set nocount on '+@temTable+@sql+@part2+' set nocount off') --打开影响行数 GO
调用方法示例:
SET STATISTICS IO on -- 查看磁盘IO
set statistics time on -- 查看sql语句分析编译和执行时间
declare @count int
set @count=0
exec [dbo].[Erp_Common_PageList_TemTableByRelation] 1,50,@count,'or_id','dateSta desc',
' * ','orders','','','orders on spkid=or_id','',''
总结:在读取数据过程中尽可能的减少表逻辑读取次数,以及扫描次数,减少io输出是提高性能的保证。