我正在使用一个我没写过的存储过程,它很长并且包含许多列和连接。该过程返回一个游标,应用程序服务器(.NET,顺便提一下)接收并迭代。
我正在尝试使用SQLPlus和PL / SQL拦截游标,但我很难弄清楚如何设置脚本。这是我到目前为止所做的:
DECLARE
cur sys_refcursor;
BEGIN
adv_schema.report_proc('CAL','01-JAN-2011','01-JAN-2012','Y',cur);
OPEN cur FOR --??????
LOOP
FETCH cur INTO column1, column2;
EXIT WHEN cur%NOTFOUND;
DBMS_OUTPUT.Put_Line ('First Name: '||column1||' Last Name: '||column2);
END LOOP;
END;
/
我在OPEN声明中添加了什么?我所见过的关于如何执行此操作的所有示例都是过于简化的示例,其中在PL / SQL块中创建了一些表't',然后打开了一个带有查询到该表的游标,以进行循环。过程何时将游标返回到具有多个表的复杂查询?
答案 0 :(得分:5)
假设report_proc
过程正在返回游标(即第四个参数定义为OUT SYS_REFCURSOR
),则代码中不需要OPEN
光标。该程序已经打开它。你只需要从中获取。
答案 1 :(得分:4)
正如@Justin已经提到的,不需要打开report_proc
过程返回的游标,只需要从该游标中获取。 Ref游标是弱游标(基本上没有返回类型的游标),并且为了从弱类型游标中获取,你需要知道要获取什么。当您知道游标返回的类型时,您可以声明要获取的本地结构,如下所示:
DECLARE
-- example of record
-- in your case you have to know exactly
-- how many column and of which datatype your ref cursor returns
type T_Record is record(
column_1 number,
column_2 number
);
l_record T_Record;
cur sys_refcursor;
BEGIN
adv_schema.report_proc('CAL','01-JAN-2011','01-JAN-2012','Y',cur);
LOOP
FETCH cur
INTO l_record;
EXIT WHEN cur%NOTFOUND;
DBMS_OUTPUT.Put_Line ('First Name: '||l_record.column1
||' Last Name: '||l_record.column2);
END LOOP;
END;
此外,如果您只需要打印引用游标的内容,您可以在SQL * Plus中执行以下操作:
SQL> variable cur refcursor;
SQL> exec adv_schema.report_proc('CAL','01-JAN-2011','01-JAN-2012','Y', :cur);
然后使用print命令打印 refcursor cur
:
SQL> print cur;
我是否需要获取光标返回的每一列,或者我可以获取一个子集,比如说前三个。
不,您获取所有内容,您无法选择要获取的列。但是,这并非不可能,但它将涉及使用dbms_sql
包,特别是dbms_sql.describe_columns
过程来获取有关游标列的信息。
仅供考虑,如果您知道游标中确实存在特定列,则可以使用xmlsequence()
函数来获取在extract()
函数中指定其名称的特定列:
SQL> declare
2 type T_List is table of varchar2(123);
3 l_names T_List;
4 l_ref_cur sys_refcursor;
5
6 begin
7 open l_ref_cur
8 for select first_name, last_name
9 from employees
10 where rownum <= 5;
11
12 SELECT t.extract('ROW/FIRST_NAME/text()').getstringval()
13 bulk collect into l_names
14 FROM table(xmlsequence(l_ref_cur)) t;
15
16 for indx in l_names.first..l_names.last
17 loop
18 dbms_output.put_line(l_names(indx));
19 end loop;
20 end;
21 /
结果:
Ellen
Sundar
Mozhe
David
Hermann
PL/SQL procedure successfully completed