下面的代码我不能将fetch-into-variable的类型声明为基础表的%ROWTYPE,因为SYS_REFCURSOR位于连接两个表的select上,并且还选择了几个基于两个表的属性调用的函数.即我不能声明为L_RECORD T%ROWTYPE
--- DECLARE P_RS SYS_REFCURSOR; L_RECORD P_RS%ROWTYPE; BEGIN CAPITALEXTRACT( P_RS => P_RS ); OPEN P_RS; LOOP BEGIN FETCH P_RS INTO L_RECORD; EXIT WHEN P_RS%NOTFOUND; ... EXCEPTION WHEN OTHERS THEN ... END; END LOOP; CLOSE P_RS; END; -------- CREATE or REPLACE PROCEDURE CAPITALEXTRACT ( p_rs OUT SYS_REFCURSOR ) AS BEGIN OPEN p_rs for select t.*,tminusone.*,f(t.cash),g(t.cash) FROM T t,TMINUSONE tminusone where t.ticket=tminusone.ticket; END CAPITALEXTRACT;
当然,我不想在SYS_REFCURSOR中返回带有列的静态表R,然后声明为L_RECORD R%ROWTYPE.
因此问题是:
如何声明一个弱类型SYS_REFCURSOR变量的%ROWTYPE?
简短的回答是,你做不到.您需要为每个要返回的列定义一个变量.
原文链接:https://www.f2er.com/oracle/205267.htmlDECLARE P_RS SYS_REFCURSOR; L_T_COL1 T.COL1%TYPE; L_T_COL1 T.COL2%TYPE; ...
然后获取列列表:
FETCH P_RS INTO L_T_COL1,L_T_COL2,... ;
只要你知道你在ref游标中期待什么,这是痛苦但可管理的.在你的过程中使用T. *会使这个变得脆弱,因为向表中添加一列会破坏认为它知道列有哪些列以及它们处于什么顺序的代码.(如果表格也可以在环境之间中断它并不是一致的 – 我已经看到不同环境中列排序不同的地方).您可能希望确保您只选择您真正关心的列,以避免为您永远不会阅读的内容定义变量.
从11g开始,您可以使用DBMS_SQL
软件包将sys_refcursor转换为DBMS_sql游标,您可以查询它以确定列.作为您可以执行的操作的示例,这将使用列名打印出每行中每列的值:
DECLARE P_RS SYS_REFCURSOR; L_COLS NUMBER; L_DESC DBMS_sql.DESC_TAB; L_CURS INTEGER; L_VARCHAR VARCHAR2(4000); BEGIN CAPITALEXTRACT(P_RS => P_RS); L_CURS := DBMS_sql.TO_CURSOR_NUMBER(P_RS); DBMS_sql.DESCRIBE_COLUMNS(C => L_CURS,COL_CNT => L_COLS,DESC_T => L_DESC); FOR i IN 1..L_COLS LOOP DBMS_sql.DEFINE_COLUMN(L_CURS,i,L_VARCHAR,4000); END LOOP; WHILE DBMS_sql.FETCH_ROWS(L_CURS) > 0 LOOP FOR i IN 1..L_COLS LOOP DBMS_sql.COLUMN_VALUE(L_CURS,L_VARCHAR); DBMS_OUTPUT.PUT_LINE('Row ' || DBMS_sql.LAST_ROW_COUNT || ': ' || l_desc(i).col_name || ' = ' || L_VARCHAR); END LOOP; END LOOP; DBMS_sql.CLOSE_CURSOR(L_CURS); END; /
这并没有太多实际用途,为简洁起见,我将每个值都视为一个字符串,因为我只想打印它.查看文档并搜索更实际应用的示例.
如果你只需要你的ref游标中的几列,我想,你可以循环l_desc并记录column_name是你感兴趣的任何位置,作为一个数值变量;然后,您可以通过该变量引用该列,稍后您通常会在游标循环中使用该名称.取决于您对数据的处理方式.
但是,除非你期望不知道你要回来的列顺序,这是不可能的,因为你似乎控制了程序 – 并假设你摆脱了.* s – 你可能会更好地减少返回列到您需要的最小值,并且只是单独声明它们.