select * from ( select CustomerId, ROW_NUMBER() OVER (order by CustomerId) as Pos from CRMCustomer ) as T where T.Pos BETWEEN 1 and 10
sql2000
set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go ALTER PROCEDURE [dbo].[PageSplit] -- Add the parameters for the stored procedure here @SQL Nvarchar(max), @Order Nvarchar(20), @CurPage int, @PageRows int, @TotalRecorder int output AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from DECLARE @Str nVARCHAR(4000),@ID VARCHAR(255),@ExceSQL VARCHAR(255) set @ID = @Order WITH tmp AS (SELECT * FROM INFO) select @TotalRecorder=COUNT(*) from tmp SET @Str='SELECT TOP '+CAST(@PageRows AS VARCHAR(20))+' * FROM ('+@SQL+') T WHERE T.'+@ID+' NOT IN (SELECT TOP '+CAST((@PageRows*(@CurPage-1)) AS VARCHAR(20))+''+@ID+' FROM ('+@SQL+') T9 ORDER BY '+@Order+') ORDER BY '+@Order PRINT @Str EXEC sp_ExecuteSql @Str END
sql2005
ALTER PROCEDURE [dbo].[PageSplit] -- Add the parameters for the stored procedure here @SQL Nvarchar(max), @Order Nvarchar(20), @CurPage int, @PageRows int, @TotalRecorder int output AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from SET NOCOUNT ON; declare @ExceSQL nvarchar(max) --設置開始行號 declare @start_row_num AS int SET @start_row_num = (@CurPage -1) * @PageRows --設置標識語句 --declare @RowNumber nvarchar(100) --set @RowNumber =', ROW_NUMBER() OVER(ORDER BY '+ @Order +') as RowNumber from ' --set @SQL = Replace(@SQL,' from ',@RowNumber) set @SQL ='select * ,ROW_NUMBER() OVER(ORDER BY TT.'+ @Order +') as RowNumber from ('+ @SQL +') TT' --獲得總記錄數 set @ExceSQL ='WITH tmp AS ('+ @SQL +') select @TotalRecorder=max(RowNumber) from tmp' execute sp_executesql @ExceSQL,N'@TotalRecorder int output',@TotalRecorder output --設置查詢語句 set @ExceSQL ='WITH tmp AS ('+ @SQL +') select * from tmp where RowNumber >' + Convert(nvarchar,@start_row_num) +' And RowNumber <= '+ Convert(nvarchar,@start_row_num+@PageRows) execute(@ExceSQL) END
Oracle
其一
CREATE OR REPLACE PACKAGE SplitPage is type Splitlist is REF CURSOR; PROCEDURE SPLITDATA ( SqlStr in varchar2, pagesize in integer, PageIndex in integer, RecordCount out integer, retunlist out Splitlist ); end SplitPage; / CREATE OR REPLACE PACKAGE body SplitPage IS Procedure SplitData ( ----IN------ -- 传入进行分页的SQL语句 SqlStr in varchar2, -- 页大小 PageSize in integer, -- 需要获取的当前页码 PageIndex in integer, ----OUT------ -- 返回记录总数 RecordCount out integer, --返回执行后的游标(数据集) RetunList out Splitlist ) AS v_splitsql varchar2(1000); --正式用来查询的SQL语句 v_exutteSQL varchar2(1000);--用来存储Select SQL语句中从From开始的以后所有字符 v_listSizeSQL varchar2(1000);--用来组织获取数据统计SQL v_CurrPage int; --当前页码 --v_MaxSize int;--最大行 v_MinLine int; --最小行 v_MaxLine int; --最大行 v_MaxPage integer; --最大页 begin --修改SQL语句,插入Rownum字段作为ID select SubStr(trim(SqlStr),7,1000) into v_exutteSQL from dual; v_splitsql:='select rownum splitID,'||v_exutteSQL; --清空exutteSQL v_exutteSQL:=''; select SubStr(SqlStr,instr(SqlStr,'from'),1000) into v_exutteSQL from dual; --组织新的SQL语句 v_listSizeSQL:='select count(*) '||v_exutteSQL; --执行SQL语句 execute immediate v_listSizeSQL into RecordCount; --取得最大页数 v_MaxPage := ceil(RecordCount/PageSize); --检查当前页码是否符合要求 if PageIndex>v_MaxPage then v_CurrPage:=v_MaxPage; else v_CurrPage:=PageIndex; end if; --取得当前最小行数 if (v_CurrPage-1>0) then v_MinLine:=(v_CurrPage-1)*PageSize; else v_MinLine:=0; end if; --取得当前最大行数 v_MaxLine:=v_CurrPage*PageSize; v_splitsql:='select * from ('||v_splitsql||') where splitID>'||v_MinLine||' and splitID<='||v_MaxLine; open RetunList for v_splitsql; END SplitData; END SplitPage; /
其二
create or replace package PKG_PageSplit is TYPE mytype IS REF CURSOR; Procedure GetRecords ( p_PageSize Int, --每页记录数 p_PageIndex Int, --当前页码,从 1 开始 p_SqlSelect Varchar2, --查询语句,含排序部分 p_RecordIndex Int Default 0,--单条记录ROWNUM索引编号:如果值为0则返回分页的记录集,如果值不为0则返回具体的记录 p_OutRecordCount Out Int, --返回总记录数 p_OutPageCount Out Int, --返回总的页数 p_OutCursor out mytype --返回记录集 ); end PKG_PageSplit; / create or replace package body PKG_PageSplit is Procedure GetRecords( p_PageSize Int, --每页记录数 p_PageIndex Int, --当前页码,从 1 开始 p_SqlSelect Varchar2, --查询语句,含排序部分 p_RecordIndex Int Default 0,--单条记录ROWNUM索引编号:如果值为0则返回分页的记录集,如果值不为0则返回具体的记录 p_OutRecordCount Out Int, --返回总记录数 p_OutPageCount Out Int, --返回总的页数 p_OutCursor out mytype --返回记录集 ) as v_sql Varchar2(8000); v_count Number; v_lowRownum Number; v_heiRownum Number; v_selectfields Varchar2(4000); --要查询的字段 v_tablenames Varchar2(1000); --多个表名称 v_wherecondition Varchar2(3000); --where条件子句 v_posfrom Number; --from的位置 v_posselect Number; --select的位置 v_poswhere Number; --where条件的位置 v_posorderby Number; --order by的位置 v_primaryTable Varchar2(1000); --表示记录中的主记录的表 v_tmpwhereint Number; --临时保存where的位置 v_tmpfromint Number; --临时保存from的位置 v_tmpint Number; v_tmpstr Varchar2(8000); v_flag Number; v_tablecountsflag Number; Begin v_flag :=0; --默认状态 v_tablecountsflag :=0; ------------------------------------------------------------先处理相关变量 v_posfrom := instr(lower(p_SqlSelect), 'from ', 1,1); --查找第一个from的位置 v_selectfields := substr(p_SqlSelect,1,v_posfrom-1); --取出第一个from之前的select ###### --判断语句是否还有select子句 v_tmpfromint := instr(lower(v_selectfields),'from ',v_posfrom+5,1); --查找出第二个from的位置 If v_tmpfromint >0 Then --如果第二个from存在,需要判断是否第一个select和第一个from之间是否有select v_posselect := instr(lower(substr(p_SqlSelect,1,v_posfrom)),'select ',1,2); If v_posselect >0 Then --说明在查询的字段中有 select from 子语句,情况较复杂 --格式:S--(S--F)----F--. v_flag :=1; Goto do_flag; Else --说明第二个from是 视图或者where条件中的从句,第一个from就是最外层的 from --格式:S--F--(..F..)-- --v_selectfields := substr(p_SqlSelect,1,v_posfrom-1); --取出第一个from之前的select ###### --判断两个from之间是否还有where条件 v_poswhere := instr(lower(p_SqlSelect), 'where ', v_posfrom+5,1); --查找两个from之间的where,这也是第一个where If v_poswhere < v_tmpfromint And v_poswhere > v_posfrom Then --两个from之间有where ,说明第二个from是where条件中的 select from子句 --格式:S--F--W--(..F..)-- v_wherecondition := substr(p_SqlSelect,v_poswhere); v_tablenames := substr(p_SqlSelect,v_posfrom+5,v_poswhere-(v_posfrom+5)); Goto do_flag; Elsif v_poswhere > v_tmpfromint Then --where的位置大于第二个from ,说明 from的视图或表是一个子查询 --格式:S--F--(S--F--W) --这里需要判断在第一个where之后是否还有where, v_tmpwhereint := instr(lower(p_SqlSelect), 'where ', v_poswhere+6,1); --取出全局中第二个where的位置 If v_tmpwhereint >0 Then --现在的格式:S--F--S--F--W--..W..-- 情况交复杂 v_flag :=1; Goto do_flag; Else --全局中仅有一个where,这里需要判断where是全局查询条件 还是 from的视图查询条件 --通过判断第二个from和第一个where之间是否有‘)’符号 v_tmpstr := substr(p_SqlSelect,v_tmpfromint+5,v_poswhere-(v_tmpfromint+5)); If instr(v_tmpstr,')',-1,1) >0 Then --说明where是全局查询条件 Goto do_sfw1; Else --说明where是from视图的查询条件 Goto do_orderby; End If; End If; Else --没有查询到where条件的位置,说明一个where条件都没有 Goto do_orderby; End If; End If; End If; -------如果没有select from子句,全局找不到第二个 from ----------------------------------- <<do_sfw1>> v_selectfields := substr(p_SqlSelect,1,v_posfrom-1); --取出第一个from之前的select ###### --如果没有select from子句,查找where的位置 v_poswhere := instr(lower(p_SqlSelect), 'where ', v_posfrom+4,1); --查找第一个where的位置 --判断语句中第一个where是否存在 If v_poswhere >0 Then --存在 v_wherecondition := substr(p_SqlSelect,v_poswhere); v_tablenames := substr(p_SqlSelect,v_posfrom+5,v_poswhere-(v_posfrom+5)); Goto do_flag; End If; <<do_orderby>> --如果语句中没有where条件,先查询是否有order by 排序条件 从字符串最后一个字符查找 v_posorderby := instr(lower(p_SqlSelect), 'order by ', -1,1); --查找order by的位置 If v_posorderby >0 Then --如果语句中有order by v_wherecondition := substr(p_SqlSelect,v_posorderby); v_tablenames := substr(p_SqlSelect,v_posfrom+5,v_posorderby-(v_posfrom+5)); Else --如果语句中也没有order by v_wherecondition :=''; v_tablenames := substr(p_SqlSelect,v_posfrom+5); End If; <<do_flag>> If v_flag <=0 Then --这里要处理获得primarytable主视图表的名称 <<do_primarytable>> v_tablenames := trim(v_tablenames); v_tmpint := instr(v_tablenames,',',1,1); If v_tmpint >0 Then --判断是否是多个表的联合查询 v_primaryTable := substr(v_tablenames,1,v_tmpint-1); v_tablecountsflag :=1; --标识符说明有多个表 Else v_tmpint := instr(lower(v_tablenames),'join',1,1); If v_tmpint >0 Then v_primaryTable := substr(v_tablenames,1,v_tmpint-1); v_primaryTable := Replace(v_primaryTable,'out',''); v_primaryTable := Replace(v_primaryTable,'left',''); v_primaryTable := Replace(v_primaryTable,'right',''); v_primaryTable := Replace(v_primaryTable,'inner',''); Else v_primaryTable := v_tablenames; End If; End If; v_primaryTable := lower(trim(v_primaryTable)); v_primaryTable := replace(replace(v_primaryTable,chr(13)),chr(10)); --去除换行符 --去除多个空格的情况 v_primaryTable := Replace(v_primaryTable,'',''); --去除3个连续空格 v_primaryTable := Replace(v_primaryTable,'',''); --去除2个连续空格 v_tmpint := instr(v_primaryTable,'',1,1); If v_tmpint >0 Then v_primaryTable := trim(substr(v_primaryTable,v_tmpint+1)); Else --当没有设置表的别名, 自己给定别名 v_tmpstr := v_primaryTable ||' xxjmytb'; v_tablenames := Replace(lower(v_tablenames),v_primaryTable,v_tmpstr); --先将WHERE和SELECT变量中的'转义 --v_wherecondition := Replace(v_wherecondition,chr(39),''''); --v_selectfields := Replace(v_selectfields,chr(39),''''); --还要替换掉where条件中的表名称的 v_wherecondition := lower(v_wherecondition); v_wherecondition := Replace(v_wherecondition,v_primaryTable||'.','xxjmytb.'); --还有替换掉selectfields中的表名称 v_selectfields :=lower(v_selectfields); v_selectfields := Replace(v_selectfields,v_primaryTable||'.','xxjmytb.'); v_tmpint := instr(v_primarytable,'.',-1,1); --查找带点的表名 If v_tmpint >0 Then v_tmpstr := trim(substr(v_primarytable,v_tmpint+1)); v_tmpstr := v_tmpstr||'.'; v_wherecondition := Replace(v_wherecondition,v_tmpstr,'xxjmytb.'); v_selectfields := Replace(v_selectfields,v_tmpstr,'xxjmytb.'); --替换掉selectfields中的表名称 End If; v_primarytable :='xxjmytb'; End If; v_tablenames :=''|| v_tablenames ||''; ---取分页总数-----------------------目的是为了在统计的时候将字段中的相关方法出去 v_sql :='select count(*) from '|| v_tablenames || v_wherecondition; Execute Immediate v_sql Into v_count; p_OutRecordCount := v_count; --将总记录数赋值给返回的参数 p_OutPageCount := ceil(v_count/p_PageSize); --将总页数赋值给返回的参数 v_heiRownum := p_PageIndex * p_PageSize; v_lowRownum := v_heiRownum - p_PageSize +1; --计算开始和起始位置 v_sql :='select '|| v_primaryTable ||'.rowid as xxjid,rownum as rownn_xxj from '|| v_tablenames || v_wherecondition; v_sql :='select xxjid,rownum as rownn_xxj from ('|| v_sql ||') where rownn_xxj <='|| to_char(v_heiRownum); v_sql :='select xxjid from ('|| v_sql ||') where rownn_xxj >= '|| to_char(v_lowRownum); If v_tablecountsflag >0 Then v_sql := v_selectfields ||',rownum as rownn_xxj from '|| v_tablenames ||',('|| v_sql ||') xxjlast where xxjlast.xxjid='|| v_primaryTable ||'.rowid and '|| substr(trim(v_wherecondition),6); Else v_sql := v_selectfields ||',rownum as rownn_xxj from '|| v_tablenames ||',('|| v_sql ||') xxjlast where xxjlast.xxjid='|| v_primaryTable ||'.rowid'; End If; Else v_sql :='select count(*) from ('|| p_SqlSelect ||')'; execute immediate v_sql into v_count; p_OutRecordCount := v_count; p_OutPageCount := ceil(v_count/p_PageSize); --将总页数赋值给返回的参数 v_heiRownum := p_PageIndex * p_PageSize; v_lowRownum := v_heiRownum - p_PageSize +1; v_sql :='SELECT * FROM (SELECT A.*, rownum rownn_xxj FROM ('|| p_SqlSelect ||') A WHERE rownum <= '|| to_char(v_heiRownum) ||' ) B WHERE rownn_xxj >= '|| to_char(v_lowRownum) ; End If; --#############如果是具体某条记录的详细信息################################################ If p_RecordIndex >0 Then v_sql :='select * from ('|| v_sql ||') where rownn_xxj='||to_char(p_RecordIndex); End If; --######################################################################################### Open p_OutCursor For v_sql; End GetRecords; --------------------------------------------------------------------------------------------------------------------------- End PKG_PageSplit; /