首页源码oracle游标(Oracle 嵌套游标的威力:实现复杂查询)

oracle游标(Oracle 嵌套游标的威力:实现复杂查询)

编程之家2024-01-31162次浏览

一、oracle用游标分页查询学生所有信息

Oracle内分页:

oracle游标(Oracle 嵌套游标的威力:实现复杂查询)

1.首先创建返回结果集的包,代码如下:

--创建包

create or replace package types as

type cursorType is ref cursor;

end;12341234

2.创建实现分页查询的存储过程:

oracle游标(Oracle 嵌套游标的威力:实现复杂查询)

--创建存储过程

CREATE OR REPLACE PROCEDURE PROC_GET_DATA_PAGING(P_TABLENAME IN VARCHAR2,--表(视图)名

P_STRWHERE IN VARCHAR2,--查询条件

P_ORDERCOLUMN IN VARCHAR2,--排序的列

P_CURPAGE IN OUT NUMBER,--当前页

P_PAGESIZE IN OUT NUMBER,--每页显示记录条数

oracle游标(Oracle 嵌套游标的威力:实现复杂查询)

P_TOTALRECORDS OUT NUMBER,--总记录数

P_TOTALPAGES OUT NUMBER,--总页数

V_CUR OUT TYPES.CURSORTYPE)--返回的结果集

IS

V_SQL VARCHAR2(4000):='';--SQL语句

V_STARTRECORD NUMBER(10);--开始显示的记录条数

V_ENDRECORD NUMBER(10);--结束显示的记录条数

V_SHOWALL INTEGER;--是否显示全部记录

BEGIN

--记录中总记录条数

V_SQL:='SELECT TO_NUMBER(COUNT(*)) FROM'|| P_TABLENAME||

' WHERE 1=1';

IF P_STRWHERE IS NOT NULL OR P_STRWHERE<>'' THEN

V_SQL:= V_SQL|| P_STRWHERE;

END IF;

EXECUTE IMMEDIATE V_SQL

INTO P_TOTALRECORDS;

--验证页面记录大小

IF P_PAGESIZE<= 0 THEN

V_SHOWALL:= 1;

P_PAGESIZE:= 0;

END IF;

IF V_SHOWALL IS NULL THEN

--根据页大小计算总页数

IF MOD(P_TOTALRECORDS, P_PAGESIZE)= 0 THEN

P_TOTALPAGES:= TRUNC(P_TOTALRECORDS/ P_PAGESIZE, 0);

ELSE

P_TOTALPAGES:= TRUNC(P_TOTALRECORDS/ P_PAGESIZE, 0)+ 1;

END IF;

ELSE

P_TOTALPAGES:= 1;

END IF;

--验证页号

IF P_CURPAGE< 1 THEN

P_CURPAGE:= 1;

END IF;

IF P_CURPAGE> P_TOTALPAGES THEN

P_CURPAGE:= P_TOTALPAGES;

END IF;

--实现分页查询

V_STARTRECORD:=(P_CURPAGE- 1)* P_PAGESIZE+ 1;

V_ENDRECORD:= P_CURPAGE* P_PAGESIZE;

V_SQL:='SELECT* FROM(SELECT A.*, ROWNUM R FROM'||

'(SELECT* FROM'|| P_TABLENAME;

IF P_STRWHERE IS NOT NULL OR P_STRWHERE<>'' THEN

V_SQL:= V_SQL||' WHERE 1=1'|| P_STRWHERE;

END IF;

IF P_ORDERCOLUMN IS NOT NULL OR P_ORDERCOLUMN<>'' THEN

V_SQL:= V_SQL||' ORDER BY'|| P_ORDERCOLUMN;

END IF;

IF V_SHOWALL IS NULL THEN

V_SQL:= V_SQL||') A WHERE ROWNUM<='|| V_ENDRECORD||

') B WHERE R>='|| V_STARTRECORD;

ELSE

V_SQL:= V_SQL||') A) B';

END IF;

DBMS_OUTPUT.PUT_LINE(V_SQL);

OPEN V_CUR FOR V_SQL;

END PROC_GET_DATA_PAGING;123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172

一定要先创建返回结果集的包,否则编译存储过程有问题。

二、oracle 怎么提升游标速度

游标一般都是在执行sql语句,我不知道你指的是这个sql语句比较慢,还是单纯的游标速度慢。

sql语句慢可以根据使用改写sql语句的写法,建立索引,建立分区等优化手段来解决。

单纯游标速度慢,可以考略批量执行

bulk collect这种方式提取数据

使用forall替代for循环也可以提升效率。

以下是我总结的plsql调优的重点,你可以参考一下:

1.尽早退出循环

2. static的变量尽量放在循环的外层

3.因为and和or只要判断左边的表达式为真即可推出逻辑判断

所以

将容易出现true的逻辑表达式放在左边,这样可以省下处理的时间

4. if else和case when同上

5.尽量使用迭代,而不是递归,因为调用存储过程或者函数,会开辟另外的内存空间

6.通常函数都是值传递,即传参数的时候会copy参数的值到子程序中

对于数据量比较大的参数可以使用

in out nocopy指定引用传递,可以节省大量时间

7.可以使用关联数组,较少查找集合中元素的时间

关联数组

index by varchar2(xx)类似于map,会省下很集合操作,以及时间。

8.对于cpu密集型的plsql,可以使用native本地编译的特性

alter xxx compile plsql_code_type=native;

9.经常使用的子程序可以使用inline函数内嵌到主程序中

pragma inline($FUNCTION_NAME,'yes');

重载的程序只要拥有相同的名称都会被内嵌到program unit中

plsql_optimize_level=2的时候需要声明inline使用内联

plsql_optimize_level=3的编译的时候会自动的做这部分工作。不需要自己执行inline操作。可以使用PRAGMA INLINE(p1,'NO');禁止内联

当level=3的时候声明了inline会给予这个子程序更高的inline的优先级。

下面的语句中

(1)PRAGMA INLINE(p1,'YES');

(2)PRAGMA INLINE(p1,'NO');

(3)PRAGMA INLINE(p1,'YES');

第二行会覆盖第一行以及第三行,也就是说program unit中奖不使用内联

10.大量数字操作的时候可以使用java存储过程

11.使用result cache功能缓存经过计算得到的结果

relies_on($TB_NAME)

指定当表tb_name的数据改变时,结果集缓存失效

12.使用

update of$COLUMN_NAME on$TB_NAME

for each row

when(new.xx>1000)

可以省下需要处理时间

最好都使用after触发器,before可能会有锁定的问题

三、oracle 定义存储过程的时候,能不能循环定义多个游标

oracle没有游标数组的概念。但是你可以定义动态游标,举个例子:

declare

bm number;

zw varchar2(10);

tt number;

str varchar2(50);

type cur_type is ref cursor;--定义游标类型

cur cur_type;--定义游标变量

begin

str:='select deptno,sum(sal) from emp group by deptno';--查询字符串

open cur for str;

dbms_output.put_line('每个部门的工资总和:');

while cur%found loop

dbms_output.put_line(bm||''||tt);

fetch cur into bm,tt;

end loop;

str:='select job,avg(sal) from emp group by job';--查询字符串

open cur for str;

dbms_output.put_line('每个职位的工资总和:');

fetch cur into zw,tt;

while cur%found loop

dbms_output.put_line(zw||''||tt);

fetch cur into zw,tt;

end loop;

end;

每次通过改变str的值,来改变select语句,从而改变游标。

至于循环游标就是这样:

open cur for str;--打开游标

dbms_output.put_line('每个职位的工资总和:');

fetch cur into zw,tt;

while cur%found loop--循环

dbms_output.put_line(zw||''||tt);

fetch cur into zw,tt;

end loop;--循环结束

混播vps(混拨VPS简介:您需要知道的一切)com域名(什么是 .com 域名?含义和用途又是什么?)