分页存储过程
ROW_NUMBER的用法
select * from
(
select CustomerId, ROW_NUMBER() OVER (order by CustomerId) as Pos from CRMCustomer
) as T
where T.Pos BETWEEN 1 and 10
(
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
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
-- 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;
/
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;
/
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;
/