分页存储过程实例剖析心得

发表于:2011-10-13 10:12

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:WILLPAN    来源:51Testing软件测试网采编

  最近修改了个分页存储过程,作为菜鸟,还是从中获益良多,这里就开始今天的分页之旅了。

  1、开始还原

  下面先看一下原来的分页存储过程。

  • ALTER PROCEDURE [dbo].[sp_Sql_Paging] 
  •     @SqlDataTable        NVARCHAR(4000),        -- 表名 
  •     @PrimaryKey            NVARCHAR(4000),        -- 主键名称 
  •     @Fields                NVARCHAR(4000),        -- 要返回的字段 
  •     @pageSize            INT,                -- 页尺寸 
  •     @pageIndex            INT,                -- 页码 
  •     @recordCount        INT    OUTPUT,            -- 记录总数 
  •     @strOrderBy            NVARCHAR(4000),        -- 排序 
  •     @strWhere            NVARCHAR(4000)        -- 查询条件 
  • AS 
  • BEGIN 
  •     SET NOCOUNT ON 
  •     DECLARE @strSQL1    NVARCHAR(4000)        -- SQL语句1 
  •     DECLARE @strSQL2    NVARCHAR(4000)        -- SQL语句2 
  •     -- 创建临时表 
  •     -- 用来保存表的编号以及主键 
  •     CREATE TABLE #Temp_Paging 
  •     ( 
  •         Temp_Paging_Id INT
  •         RowNumber INT 
  •     ) 
  •     SET @strSQL1 = 'INSERT INTO [#Temp_Paging](Temp_Paging_Id, RowNumber) SELECT ' + @PrimaryKey + ', ROW_NUMBER() OVER (' + @strOrderBy + ') AS RowNumber FROM ' + @SqlDataTable + ' ' + @strWhere  
  •     EXEC SP_EXECUTESQL @strSQL1 
  •     SET @recordCount = @@ROWCOUNT -- 取得总记录数 
  •       
  •     -- 判断页索引 
  •     IF @pageIndex > @recordCount * 1.0 / @pageSize + 1.0 OR @recordCount <= @pageSize 
  •         BEGIN 
  •             SET @pageIndex = 1 
  •         END 
  •       
  •     -- 分页查询 
  •     SET @strSQL2 = 'SELECT ' + @Fields + ' FROM ' + @SqlDataTable + ' WHERE ' + @PrimaryKey + ' IN (SELECT Temp_Paging_Id FROM [#Temp_Paging] WHERE RowNumber BETWEEN ' + Str((@pageIndex - 1) * @pageSize + 1) + ' AND ' + Str(@pageIndex * @pageSize) + ') ' + @strOrderBy 
  •     EXEC SP_EXECUTESQL @strSQL2 
  •     DROP TABLE #Temp_Paging -- 删除临时表 
  • END
  •   从原分页存储过程很容易看出,这里运用了临时表保存编号,然后在通过pageIndex和pageSize计算所得,进行分页。

      因为这里还以主键作为查询条件,故临时表中也保存了主键值。

      很显然,这里的临时表无法做到通用,因为主键的类型不一定是上面定义的INT型,也可以是其它的类型,比如:uniqueidentifier(全球唯一标识)。

      这样的话,这个存储过程就碰到了问题,所以必须进行改进。

      2、思路一

      思路一很简单,那就把这个类型声明成一个变量,然后通过系统表获取表的主键类型,再赋给变量不就可以了吗。看起来很美妙,不妨试一试先。

      我们可以插入下面一段代码:

  • DECLARE @colType NVARCHAR(50)  --主键列类型 
  • DECLARE @strSQL3 NVARCHAR(500) --创建临时表语句 
  • SET @colType = (SELECT typ.name as 数据类型 
  •                 FROM sys.columns col  
  •                 left join sys.types typ  
  •                 on (col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id) 
  •                 WHERE col.object_id = (SELECT object_id FROM sys.tables WHERE name = @SqlDataTable) 
  •                 and exists  
  •                 ( SELECT 1 FROM sys.indexes idx  
  •                     join sys.index_columns idxCol  
  •                       on (idx.object_id = idxCol.object_id) 
  •                     WHERE idx.object_id = col.object_id 
  •                       AND idxCol.index_column_id = col.column_id  
  •                       AND idx.is_primary_key = 1 
  •                 )) 
  • SET @strSQL3 = 'CREATE TABLE #Temp_Paging 
  •                 ( 
  •                     Temp_Paging_Id '+ @colType+'
  •                     RowNumber INT  
  •                 )' 
  • PRINT @strSQL3 
  • --EXEC(@strSQL3)
  •   打印结果:

  • CREATE TABLE #Temp_Paging 
  •                 ( 
  •                     Temp_Paging_Id uniqueidentifier, 
  •                     RowNumber INT  
  •                 )
  • 21/212>
    《2023软件测试行业现状调查报告》独家发布~

    关注51Testing

    联系我们

    快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

    法律顾问:上海兰迪律师事务所 项棋律师
    版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
    投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

    沪ICP备05003035号

    沪公网安备 31010102002173号