我已经使用Oracle(10g.2)作为PHP程序员将近3年了,但是当我完成作业时,我第一次尝试使用ref游标和集合类型。和我 当我遇到问题时,我已经搜索过网络了,这个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错误。
答案 0 :(得分:6)
您使用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).
我不确定你要在这里完成什么,你在过程中获取引用游标,然后返回另一个具有相同数据的引用游标。我认为在程序中根本不需要获取光标。让调用应用程序执行提取(此处提取由print
完成。)
您正在使用动态打开的游标,我认为这是您获得无用错误消息的部分原因。如果我们使用固定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,e.ENAME,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对象中不。
PLS-00306
:错误的参数数量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, e.ENAME, 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的文档。