我已经使用Oracle(10g.2)作为
PHP程序员将近3年,但是当我完成一项任务时,我第一次尝试使用ref游标和集合类型.和我
当我遇到问题时,我已经搜索过网络了,这个ora-00932错误让我感到不知所措.我需要老手的帮助.
当我遇到问题时,我已经搜索过网络了,这个ora-00932错误让我感到不知所措.我需要老手的帮助.
这是我一直在努力解决的问题,
我想从表中选择行并将它们放在引用游标中,然后使用记录类型将它们收集在一个关联数组中.再次从这个关联数组中,创建一个引用游标.不要问我为什么,我正在写这么复杂的代码,因为我需要它来进行更复杂的分配.我可能会让你感到困惑,因此让我告诉你我的代码.
我在Toad的类型选项卡下定义了两种类型.其中一个是对象类型:
CREATE OR REPLACE TYPE R_TYPE AS OBJECT(sqn number,firstname VARCHAR2(30),lastname VARCHAR2(30));
另一个是使用上面创建的对象类型的集合类型:
CREATE OR REPLACE TYPE tr_type AS TABLE OF r_type;
然后我创建一个包:
CREATE OR REPLACE PACKAGE MYPACK_PKG IS TYPE MY_REF_CURSOR IS REF CURSOR; PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR); END MYPACK_PKG;
包装体:
CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS rcur MYPACK_PKG.MY_REF_CURSOR; sql_stmt VARCHAR2(1000); l_rarray tr_type := tr_type(); l_rec r_type; BEGIN sql_stmt := 'SELECT 1,e.first_name,e.last_name FROM hr.employees e '; OPEN rcur FOR sql_stmt; LOOP fetch rcur into l_rec; exit when rcur%notfound; l_rarray := tr_type( l_rec ); END LOOP; CLOSE rcur; --OPEN r_cursor FOR SELECT * FROM TABLE(cast(l_rarray as tr_type) ); END MY_PROC; END MYPACK_PKG;
我注释掉了打开引用光标的最后一行.因为当我在Toad的sql编辑器中运行该过程时它会导致另一个错误,这是我要问的第二个问题.
最后我在Toad中运行代码:
variable r refcursor declare r_out MYPACK_PKG.MY_REF_CURSOR; begin MYPACK_PKG.MY_PROC(r_out); :r := r_out; end; print :r
在那里我得到了ora-00932错误.
您使用REF CURSOR的方式并不常见.这将是使用它们的标准方式:
sql> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS 2 PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS 3 BEGIN 4 OPEN r_cursor FOR SELECT e.empno,e.ENAME,null FROM scott.emp e; 5 END MY_PROC; 6 END MYPACK_PKG; 7 / Corps de package crÚÚ. sql> VARIABLE r REFCURSOR sql> BEGIN 2 MYPACK_PKG.MY_PROC(:r); 3 END; 4 / ProcÚdure PL/sql terminÚe avec succÞs. sql> PRINT :r EMPNO ENAME N ---------- ---------- - 7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN [...] 14 ligne(s) sÚlectionnÚe(s).
我不确定你要在这里完成什么,你在程序中获取引用游标,然后返回另一个具有相同数据的引用游标.我认为在程序中根本不需要获取光标.让调用应用程序进行提取(这里提取由打印完成).
更新:为什么你收到无用的错误消息?
您正在使用动态打开的游标,我认为这是您获得无用错误消息的部分原因.如果我们使用固定sql,则错误消息不同:
sql> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS 2 PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS 3 TYPE type_rec IS RECORD (qn number,4 firstname VARCHAR2(30),5 lastname VARCHAR2(30)); 6 lt_record type_rec; /* Record type */ 7 lt_object r_type; /* sql Object type */ 8 BEGIN 9 OPEN r_cursor FOR SELECT e.empno,null FROM scott.emp e; 10 FETCH r_cursor INTO lt_record; /* This will work */ 11 FETCH r_cursor INTO lt_object; /* This won't work in 10.2 */ 12 END MY_PROC; 13 END MYPACK_PKG; 14 / Package body created sql> VARIABLE r REFCURSOR sql> BEGIN 2 MYPACK_PKG.MY_PROC(:r); 3 END; 4 / BEGIN * ERREUR Ó la ligne 1 : ORA-06504: PL/sql: Return types of Result Set variables or query do not match ORA-06512: at "APPS.MYPACK_PKG",line 11 ORA-06512: at line 2
我概述了目前在10.2中你可以将游标提取到PLsql记录中而不是在sql对象中.
l_rarray是一个NESTED TABLE,它需要初始化然后扩展才能存储元素.例如:
sql> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS 2 PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS 3 lr_array tr_type := tr_type(); /* sql Array */ 4 BEGIN 5 FOR cc IN (SELECT e.empno,NULL lastname 6 FROM scott.emp e) LOOP 7 lr_array.extend; 8 lr_array(lr_array.count) := r_type(cc.empno,9 cc.ename,10 cc.lastname); 11 /* Here you can do additional procedural work on lr_array */ 12 END LOOP; 13 /* then return the result set */ 14 OPEN r_cursor FOR SELECT * FROM TABLE (lr_array); 15 END MY_PROC; 16 END MYPACK_PKG; 17 / Corps de package crÚÚ. sql> print r SQN FIRSTNAME LASTNAME ---------- ------------------------------ ----------- 7369 SMITH 7499 ALLEN 7521 WARD [...] 14 ligne(s) sÚlectionnÚe(s).
如需进一步阅读,您可以浏览PL/SQL collections and records的文档.