公用ms sql 分页存储过程

  在编写分页存储过程前我们先为数据库创建一个测试表,这个测试表明叫做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该存储过程执行会发生异常;需要执行两次检索表,花费资源大;当选择第二页,还需要执行两次,一次是列表,一次是统计总数。

  现在在同等情况下为了提高性能,提高语句执行效率。需要对以上的分页存储过程的逻辑思路进行个调整:

  在未统计分页总数情况统计分页总数,当已经统计过分页总数,可不需要再次统计分页总数。

  在我们第一位统计分页总数时,我们需要统计分页总数,现在我们使用临时表将符合条件的记录id插入到临时表,以方便检索以及统计。 这样我们就避免来两次扫描全表。

  在多表关联筛选数据情况下,我们筛选的条件可能就只在某几张表,而显示结果可能需要关联更多的表情况下,那我们可以将筛选插入临时表的关联条件与显示列表关联条件作成不一样。以准证兼容更强。

  在我们执行分页过程中,可能会产生中间临时表去管理其他的表。

  以及完成之后我们可以直接使用到的临时表删除释放资源,而不是等待sql帮我做垃圾回收处理。

  更具以上的思路,现在我直接把代码贴出来:

--综合公用分页存储过程
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输出是提高性能的保证。

时间: 2024-08-22 05:37:42

公用ms sql 分页存储过程的相关文章

asp.net中常用到的SQL分页存储过程

asp.net中常用到的SQL分页存储过程 以下是引用片段:create PROCEDURE [dbo].[myPage] @tblName varchar(255), -- 表名 @fldName varchar(255), -- 排序的字段名,一般为唯一标识 @strGetFields varchar(1000) = ' * ', -- 需要返回的列  @PageSize int = 10, -- 每页有多少条记录 @PageIndex int = 1, -- 第几页 @Count int 

MS SQL的存储过程可以调试吗

存储过程 随着对MS SQL的存储过程的使用,存储过程中的代码越写越长,但是对存储过程中的变量及代码执行情况不能准确把握,如何像在程序中调试一样来调试MS-SQL的存储过程 1.如果调试存储过程 在查询分析器中找到需要调试的存储过程,右键点击选择"调试",弹出"调试过程"对话框,在其中输入存储过程中的参数(如果值为空,需要选择"设置为空"选项),点击"执行"即可操作 操作快捷键: F5(运行) F9(设置断点) F11(单步执

sql 分页存储过程实现代码

sql 分页存储过程实现代码 create PROCEDURE Sp_Conn_Sort ( @tblName   varchar(255),       -- 表名 @strGetFields varchar(1000) = '*',  -- 需要返回的列 @fldName varchar(255)='',      -- 排序的字段名 @PageSize   int = 40,          -- 页尺寸 @PageIndex  int = 1,           -- 页码 @doC

两款sql 分页存储过程代码

文章收藏了两款sql 分页存储过程代码,这二款存储过程是二款高效分页存储过程代码,如果你觉得自己写的语句不够,强的话,可以利用我们现成的高效分页存储过程实例代码. create procedure pages @tablenames varchar(200), --表名,可以是多个表,但不能用别名 @primarykey varchar(100), --主键,可以为空,但@order为空时该值不能为空 @fields varchar(800), --要取出的字段,可以是多个表的字段,可以为空,为

经过优化测试的SQL分页存储过程

  建立一个 Web 应用,分页浏览功能必不可少.这个问题是数据库处理中十分常见的问题.经典的数据分页方法是:ADO 纪录集分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页.但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存.游标一建立,就将相关的记录锁住,直到取消游标.游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作.而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的

mssql server sql分页存储过程

一款很简单的sql分布存储过程代码,并且是一款通用分页sql哦 . set quoted_identifier on go set ansi_nulls on go create proc execbypage @sqlquery varchar(2000), --//输入参数:sql检索语句或表名 @pagesize int, --//输入参数:每页显示记录条数 @pageindex int --//输入参数:当前页码 as set nocount on set ansi_warnings o

sql分页存储过程可带分页查询条件

假设数据库中有张表,表名是UserName,字段分别是ID(int),Name(nvarchar),Age(int). 如果不带查询条件存储过程是:  代码如下 复制代码 CREATE PROCEDURE [dbo].[UserName]     @pageIndex int,     @pageSize int AS     declare @min int;     declare @max int;     set @min=@pageSize*(@pageIndex-1)+1;    

二个sql分页存储过程实例代码

这个还觉得不错的一个存储过程  代码如下 复制代码 /****** 对象:  StoredProcedure [dbo].[P_viewPage]    脚本日期: 05/14/2012 08:49:34 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO create PROC [dbo].[P_viewPage] -- Add the parameters for the stored procedure here @TableN

SQL分页存储过程 支持连接查询等复杂的SQL

CREATE PROCEDURE Pagination( @SQL nvarchar(1024),     @PageSize int = 20,    --分页大小 @PageIndex int = 0,    --分页索引 @Sort nvarchar(100) = '''',    --排序字段 @TotalCount int = 0 output --总数    )AS set nocount on/*声明查询字符串*/declare @strSQL nvarchar(4000) set