fej*_*oco 9 oracle stored-procedures cursor
我有一个名为Table1的表.它有很多列,其中一列是Column1.我不知道其他专栏,有时甚至可能会改变.有一个强类型的引用游标类型,它返回Table1%rowtype,名为cur_Table1.我有一个名为SP1的存储过程,其out参数类型为cur_Table1.我从另一个只看到这个存储过程的数据库调用这个SP1存储过程,而不是表或类型本身.如何从返回的游标中仅选择Column1?我知道我可以获取一个记录或变量,因为游标有列,但我只知道一个列的存在,所以我不能声明完整的记录或正确的变量数.
你可以这样做DBMS_SQL
,但它不漂亮.
表和样本数据(COLUMN1的数字为1 - 10):
create table table1(column1 number, column2 date, column3 varchar2(1000), column4 clob);
insert into table1
select level, sysdate, level, level from dual connect by level <= 10;
commit;
Run Code Online (Sandbox Code Playgroud)
使用打开引用游标并选择所有内容的过程打包:
create or replace package test_pkg is
type cur_Table1 is ref cursor return table1%rowtype;
procedure sp1(p_cursor in out cur_table1);
end;
/
create or replace package body test_pkg is
procedure sp1(p_cursor in out cur_table1) is
begin
open p_cursor for select column1, column2, column3, column4 from table1;
end;
end;
/
Run Code Online (Sandbox Code Playgroud)
从ref游标中读取COLUMN1数据的PL/SQL块:
--Basic steps are: call procedure, convert cursor, describe and find columns,
--then fetch rows and retrieve column values.
--
--Each possible data type for COLUMN1 needs to be added here.
--Currently only NUMBER is supported.
declare
v_cursor sys_refcursor;
v_cursor_number number;
v_columns number;
v_desc_tab dbms_sql.desc_tab;
v_position number;
v_typecode number;
v_number_value number;
begin
--Call procedure to open cursor
test_pkg.sp1(v_cursor);
--Convert cursor to DBMS_SQL cursor
v_cursor_number := dbms_sql.to_cursor_number(rc => v_cursor);
--Get information on the columns
dbms_sql.describe_columns(v_cursor_number, v_columns, v_desc_tab);
--Loop through all the columns, find COLUMN1 position and type
for i in 1 .. v_desc_tab.count loop
if v_desc_tab(i).col_name = 'COLUMN1' then
v_position := i;
v_typecode := v_desc_tab(i).col_type;
--Pick COLUMN1 to be selected.
if v_typecode = dbms_types.typecode_number then
dbms_sql.define_column(v_cursor_number, i, v_number_value);
--...repeat for every possible type.
end if;
end if;
end loop;
--Fetch all the rows, then get the relevant column value and print it
while dbms_sql.fetch_rows(v_cursor_number) > 0 loop
if v_typecode = dbms_types.typecode_number then
dbms_sql.column_value(v_cursor_number, v_position, v_number_value);
dbms_output.put_line('Value: '||v_number_value);
--...repeat for every possible type
end if;
end loop;
end;
/
Run Code Online (Sandbox Code Playgroud)
鉴于最初的问题,乔尼尔斯的答案仍然是正确的,所以我将其标记为这样,但我最终做了一些完全不同且更好的事情。
问题是我无法控制 SP1 的数据库,我只需要从其他地方作为第 3 方客户端调用它。现在我不仅获得了查看 SP 的权限,还获得了查看光标类型的权限。我仍然看不到表格,但现在有一个更干净的解决方案:
在另一个数据库中,我现在已被授予查看此类型的访问权限:
type cur_Table1 is ref cursor return Table1%rowtype;
Run Code Online (Sandbox Code Playgroud)
所以在我的数据库中我现在可以这样做:
mycursor OtherDB.cur_Table1;
myrecord mycursor%rowtype;
...
OtherDB.SP1(mycursor);
fetch mycursor into myrecord;
dbms_output.put_line(myrecord.Column1);
Run Code Online (Sandbox Code Playgroud)
看,我仍然不需要对表进行任何访问,我只看到光标。关键是神奇的 %rowtype 也适用于游标,而不仅仅是表。它不适用于 sys_refcursor,但适用于强类型游标。有了这段代码,我不必关心另一侧是否有任何变化,我根本不必定义所有列或记录,我只需指定我感兴趣的一列。
我真的很喜欢 Oracle 这种 OOP 态度。