oracle游标如何替代 oracle控制游标的语句

oracle中怎么代替游标

你说的资料上说的尽量不使用游标,那就是使用动态sql+execute immediate的方式了。这主要是程序设计上的问题,比如说一些表名或者字段名,可以使用变量来代替,这样写程序的时候麻烦点,但是方便日后维护。取数据用游标没什么错误,看你的存储过程,重要的是还是优化sql。或者可以使用bulk collect 批量的方式取数据。

创新互联建站从2013年成立,是专业互联网技术服务公司,拥有项目网站设计、做网站网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元临淄做网站,已为上家服务,为临淄各地企业和个人服务,联系电话:13518219792

oracle里有没有其他方法替代游标

你说的资料上说的尽量不使用游标,那就是使用动态sql+execute immediate的方式了。这主要是程序设计上的问题,比如说一些表名或者字段名,可以使用变量来代替,这样写程序的时候麻烦点,但是方便日后维护。取数据用游标没什么错误,看你的存储过程,重要的是还是优化sql。或者可以使用bulk collect 批量的方式取数据。

oracle 游标是做什么用的

游标(CURSOR)也叫光标,在关系数据库中经常使用,在PL/SQL程序中可以用CURSOR与SELECT一起对表或者视图中的数据进行查询并逐行读取。

Oracle游标分为显示游标和隐式游标。

显示游标(Explicit Cursor):在PL/SQL程序中定义的、用于查询的游标称作显示游标。

隐式游标(Implicit Cursor):是指非PL/SQL程序中定义的、而且是在PL/SQL中使用UPDATE/DELETE语句时,Oracle系统自动分配的游标。

一.显示游标

1.使用步骤

(1)定义 (2)打开 (3)使用 (4)关闭

2.使用演示

首先创建测试用表STUDENT,脚本如下:

CREATE TABLE "STUDENT" (

"STUNAME" VARCHAR2(10 BYTE),

"STUNO" VARCHAR2(4 BYTE),

"AGE" NUMBER,

"GENDER" VARCHAR2(2 CHAR)

)

(1).使用WHILE循环处理游标

create or replace PROCEDURE PROC_STU1 AS

BEGIN

--显示游标使用,使用while循环

declare

--1.定义游标,名称为cur_stu

cursor cur_stu is

select stuno,stuname from student order by stuno;

--定义变量,存放游标取出的数据

v_stuno varchar(4);

v_stuname varchar(20);

begin

--2.打开游标cur_stu

open cur_stu;

--3.将游标的当前行取出存放到变量中

fetch cur_stu into v_stuno,v_stuname;

while cur_stu%found --游标所指还有数据行,则继续循环

loop

--打印结果

dbms_output.PUT_LINE(v_stuno||'-'||v_stuname);

--继续将游标所指的当前行取出放到变量中

fetch cur_stu into v_stuno,v_stuname;

end loop;

close cur_stu; --4.关闭游标

end;

END PROC_STU1;

(2).使用IF..ELSE代替WHILE循环处理游标

create or replace PROCEDURE PROC_STU2 AS

BEGIN

--显示游标使用,使用if判断

declare

--1.定义游标,名称为cur_stu

cursor cur_stu is

select stuno,stuname from student order by stuno;

--定义变量,存放游标取出的数据

v_stuno varchar(4);

v_stuname varchar(20);

begin

--2.打开游标cur_stu

open cur_stu;

--3.将游标的当前行取出存放到变量中

fetch cur_stu into v_stuno,v_stuname;

loop

if cur_stu%found then --如果游标cur_stu所指还有数据行

--打印结果

dbms_output.PUT_LINE(v_stuno||'-'||v_stuname);

--继续将游标所指的当前行取出放到变量中

fetch cur_stu into v_stuno,v_stuname;

else

exit;

end if;

end loop;

close cur_stu; --4.关闭游标

end;

END PROC_STU2;

(3).使用FOR循环处理游标

create or replace PROCEDURE PROC_STU3 AS

BEGIN

--显示游标使用,使用for循环

declare

--定义游标,名称为cur_stu

cursor cur_stu is

select stuno,stuname from student order by stuno;

begin

for stu in cur_stu

loop

dbms_output.PUT_LINE(stu.stuno||'-'||stu.stuname);

--循环做隐含检查 %notfound

end loop;

--自动关闭游标

end;

END PROC_STU3;

(4).常用的使用EXIT WHEN处理游标

create or replace

PROCEDURE PROC_STU1_1 AS

BEGIN

--显示游标使用,使用exit when循环

declare

--1.定义游标,名称为cur_stu

cursor cur_stu is

select stuno,stuname from student order by stuno;

--定义变量,存放游标取出的数据

v_stuno varchar(4);

v_stuname varchar(20);

begin

--2.打开游标cur_stu

open cur_stu;

loop

--3.将游标的当前行取出存放到变量中

fetch cur_stu into v_stuno,v_stuname;

exit when cur_stu%notfound; --游标所指还有数据行,则继续循环

--打印结果

dbms_output.PUT_LINE(v_stuno||'-'||v_stuname);

end loop;

close cur_stu; --4.关闭游标

end;

END PROC_STU1_1;

二.隐式游标

1.使用演示

create or replace PROCEDURE PROC_STU4 AS

BEGIN

--隐式游标使用

update student set stuname='张燕广' where stuno='1104';

--如果更新没有匹配则插入一条新记录

if SQL%NOTFOUND then

insert into student(STUNO,STUNAME,AGE,GENDER)

values('1104','张燕广',18,'男');

end if;

END PROC_STU4;

2.说明

所有的SQL语句在上下文区内部都是可执行的,因为都有一个游标指向上下文区,此游标就是

SQL游标,与现实游标不同的是,SQL游标在PL/SQL中不需要打开和关闭,而是在执行UPDATE、

DELETE是自动打开和关闭。

上面例子中就是通过SQL%NOTFOUND游标属性判断UPDATE语句的执行结果决定是否需要插入新记录。

ibatis 怎么返回oracle游标

问题总结:

1.index by表不能存储在数据库中的type中,故选择嵌套表。

2.ibatis不支持oracle的复合数据类型的返回。(个人理解)

3.替代方案:用返回oracle游标来代替复合数据类型。ibatis能接受oracle游标类型。

注意此处是ibatis2.3

部分代码:

1.java

复制代码

1 private MapString,Object userStateResult(Users users)throws Exception{

2 MapString,Object param = new HashMapString,Object();

3 param.put("PRM_USERID", users.getUserid().toString());

4 param.put("PRM_OBJECTS", null);

5 param.put("PRM_TAGS", null);

6 param.put("PRM_APPCODE", null);

7 param.put("PRM_ERRMSG", null);

8 getDao().queryForList("user.prc_user_index",param);

9 if(Constant.SUCCESS.equals(param.get("PRM_APPCODE"))){

10 return param;

11 }else{

12 return null;

13 }

14 }

复制代码

返回值(包括游标的返回值)都在param这个map中

2.ibatis代码:

复制代码

1 parameterMap class="java.util.Map" id="UserIndexParam"

2 parameter property="PRM_USERID" javaType="java.lang.String"

3 jdbcType="VARCHAR" mode="IN" /

4 parameter property="PRM_OBJECTS" javaType="java.sql.ResultSet"

5 jdbcType="ORACLECURSOR" mode="OUT" resultMap="ref_object" /

6 parameter property="PRM_TAGS" javaType="java.sql.ResultSet"

7 jdbcType="ORACLECURSOR" mode="OUT" resultMap="ref_tag" /

8 parameter property="PRM_APPCODE" javaType="java.lang.String"

9 jdbcType="VARCHAR" mode="OUT" /

10 parameter property="PRM_ERRMSG" javaType="java.lang.String"

11 jdbcType="VARCHAR" mode="OUT" /

12 /parameterMap

13 ---------------------------------------------------------------------------------

14 resultMap id="ref_tag" class="com.diy.tag.entity.Tag"

15 result column="tagid" jdbcType="VARCHAR" property="tagid" /

16 result column="tagname" jdbcType="VARCHAR" property="name" /

17 /resultMap

18

19 resultMap class="com.diy.comm.cursorHandler.ObjectHandler" id="ref_object"

20 result column="OBJECTID" jdbcType="DECIMAL" property="objectid" /

21 result column="OWNERID" jdbcType="DECIMAL" property="ownerid" /

22 result column="DBUSID" jdbcType="DECIMAL" property="dbusid" /

23 result column="DUSERSID" jdbcType="DECIMAL" property="dusersid" /

24 result column="TAGID" jdbcType="VARCHAR" property="tagid" /

25 result column="USERNAME" jdbcType="VARCHAR" property="username" /

26 result column="OBJNAME" jdbcType="VARCHAR" property="objname" /

27 result column="LOVENUM" jdbcType="DECIMAL" property="lovenum" /

28 result column="INRUDUCTION" jdbcType="VARCHAR" property="inruduction" /

29 result column="CATAGROY" jdbcType="DECIMAL" property="catagroy" /

30 result column="IMAGEPATH" jdbcType="VARCHAR" property="imagepath" /

31 /resultMap

32 ---------------------------------------------------------------------------

33 procedure id="prc_user_index" parameterMap="UserIndexParam"

34 {call

35 PKG_USER.PRC_USER_INDEXVIEW(?,?,?,?,?)}

36 /procedure

复制代码

有一篇文章写的很好:大家可以参考一下

但是对于本问题没有用ibatis的TypeHandler。

因为存储过程调试可以返回游标数据,但是ibatis接受的到全部是null。不知道原因,有知道的朋友可以留言一下。

我个人猜测可能是ibatis版本问题。

3.存储过程代码(部分):

复制代码

--对象类型

CREATE OR REPLACE TYPE TAGS_INFO IS object

(

TAGID number,

TAGNAME varchar2(200)

)

--嵌套表

CREATE OR REPLACE TYPE table_tag IS TABLE OF TAGS_INFO

注意对象和嵌套表都要放在全局的。不能定义在包体中

--兴趣游标

TYPE TAGCURSOR IS REF CURSOR;

--东西游标

TYPE OBJECTCURSOR IS REF CURSOR;--这个定义在包体中

------------------------------------------------------------------------

PROCEDURE PRC_USER_INDEXVIEW(PRM_USERID IN VARCHAR2,

PRM_OBJECTS OUT OBJECTCURSOR,

PRM_TAGS OUT TAGCURSOR,

PRM_APPCODE OUT VARCHAR2,

PRM_ERRMSG OUT VARCHAR2) IS

N_FLAG NUMBER;

VAR_FIRSTTAG VARCHAR2(100);

VAR_DUSERID VARCHAR2(100);

INDEX_TAGS TABLE_TAG;

--用户兴趣标签

CURSOR CUR_USERTAG IS

SELECT C.TAGID, C.NAME

FROM USERSDETIAL A, TAGRELATION B, TAG C

WHERE A.DUSERSID = B.DUSERSID

AND B.TAGID = C.TAGID

AND A.DUSERSID = VAR_DUSERID;

--公共兴趣标签

CURSOR CUR_USERPUB IS

SELECT T.*

FROM (SELECT ROWNUM AS RNUM,

COUNT(A.DUSERSID) AS CNUM,

B.TAGID,

B.NAME

FROM TAGRELATION A, TAG B

WHERE A.TAGID = B.TAGID

GROUP BY A.DUSERSID, B.TAGID, B.NAME, ROWNUM) T

WHERE RNUM = 8

ORDER BY T.CNUM DESC;

--object

/*CURSOR CUR_OBJ(VAR_TAGID VARCHAR2) IS

SELECT ROWNUM AS RN, A.*

FROM OBJECT A

WHERE trim(A.TAGID) = VAR_TAGID

AND ROWNUM 30;*/

REC_USERTAG CUR_USERTAG%ROWTYPE;

REC_USERPUB CUR_USERPUB%ROWTYPE;

--REC_OBJ OBJECT%ROWTYPE;

BEGIN

PRM_APPCODE := PKG_COMM.DEF_OK;

PRM_ERRMSG := '';

IF PRM_USERID IS NULL THEN

PRM_APPCODE := PKG_COMM.DEF_ERR;

PRM_ERRMSG := '参数未定义';

RETURN;

END IF;

--用户详细ID是否存在

SELECT B.DUSERSID

INTO VAR_DUSERID

FROM USERS A, USERSDETIAL B

WHERE A.USERID = B.USERSID

AND A.USERID = PRM_USERID;

IF VAR_DUSERID IS NULL THEN

PRM_APPCODE := PKG_COMM.DEF_ERR;

PRM_ERRMSG := '参数无效';

RETURN;

END IF;

--1.判断是否为有效用户

SELECT NVL(A.FLAG, 1)

INTO N_FLAG

FROM USERS A, USERSDETIAL B

WHERE A.USERID = B.USERSID

AND B.DUSERSID = VAR_DUSERID;

IF N_FLAG = 1 THEN

PRM_APPCODE := PKG_COMM.DEF_ERR;

PRM_ERRMSG := '用户已被禁止登录';

RETURN;

END IF;

--2.判断用户是否有兴趣tag

FOR REC_USERTAG IN CUR_USERTAG LOOP

INDEX_TAGS := TABLE_TAG();

IF CUR_USERTAG%ROWCOUNT = 0 THEN

--获取公共兴趣游标

FOR REC_USERPUB IN CUR_USERPUB LOOP

INDEX_TAGS.EXTEND;

IF CUR_USERPUB%ROWCOUNT = 1 THEN

VAR_FIRSTTAG := REC_USERPUB.TAGID;

END IF;

INDEX_TAGS(CUR_USERPUB%ROWCOUNT) := TAGS_INFO(REC_USERPUB.TAGID,

REC_USERPUB.NAME);

END LOOP;

ELSIF CUR_USERTAG%ROWCOUNT = 1 THEN

VAR_FIRSTTAG := REC_USERTAG.TAGID;

END IF;

INDEX_TAGS.EXTEND;

INDEX_TAGS(CUR_USERTAG%ROWCOUNT) := TAGS_INFO(REC_USERTAG.TAGID,

REC_USERTAG.NAME);

--index_tags(CUR_USERTAG%ROWCOUNT).TAGNAME := REC_USERTAG.NAME;

END LOOP;

IF INDEX_TAGS.COUNT 0 THEN

/* --3. 取出object

FOR REC_OBJ IN CUR_OBJ(VAR_FIRSTTAG) LOOP

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).OWNERID := REC_OBJ.OWNERID;

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).OBJECTID := REC_OBJ.OBJECTID;

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).DBUSID := REC_OBJ.DBUSID;

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).DUSERSID := REC_OBJ.DUSERSID;

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).TAGID := REC_OBJ.TAGID;

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).LOVENUM := REC_OBJ.LOVENUM;

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).INRUDUCTION := REC_OBJ.INRUDUCTION;

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).CATAGROY := REC_OBJ.CATAGROY;

PRM_OBJECTS(CUR_OBJ%ROWCOUNT).Imagepath := REC_OBJ.Imagepath;

END LOOP;*/

--返回东西游标

OPEN PRM_OBJECTS FOR

SELECT ROWNUM AS RN, A.*, B.USERNAME

FROM OBJECT A, USERSDETIAL B

WHERE A.OWNERID = B.DUSERSID

AND TRIM(A.TAGID) = VAR_FIRSTTAG

AND ROWNUM 30;

END IF;

--tag游标

OPEN PRM_TAGS FOR

SELECT * FROM TABLE(CAST(INDEX_TAGS AS TABLE_TAG));

EXCEPTION

WHEN OTHERS THEN

PRM_APPCODE := PKG_COMM.DEF_ERR;

PRM_ERRMSG := '获取主界面数据失败' || '错误原因:' || PRM_ERRMSG || '-' || SQLERRM ||

'错误行数:' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE();

END;

---注意:a.返回游标的用open for 方法,不用关心游标的关闭。它是自动关闭的。原因:调试把游标返回值点几下,你就回发现。

b.如果报错CURSOR IS CLOESD的话,说明游标里面没有数据。所以open for 必须保证有select中有数据

c.嵌套表这里要用类似与java的构造方法写,如上

如果写成类似于java中new对象后,用set方法给嵌套表赋值的,会报错未能未能初始化的结果集。

oracle如何关闭游标?

1. 用open打开的,用close关闭

declare

cursor mycursor is

select * from emp for update;

myrecord emp%rowtype;

begin

open mycursor;

loop

fetch mycursor into myrecord;

exit when mycursor%notfound;

if (myrecord.sal=2000) then

update emp

set sal=2001

where current of mycursor;

end if;

end loop;

close mycursor;

commit;

end;

2. 用for 循环的,循环完了就自己关了

declare

cursor mycursor is

select * from emp;

begin

for i in mycursor

loop

dbms_output.put_line(i.job);

end loop;

end;


本文标题:oracle游标如何替代 oracle控制游标的语句
文章链接:http://ybzwz.com/article/doooohh.html