How do I write a stored procedure which adds a column to a ref cursor from another stored procedure?

一笑奈何 提交于 2019-12-23 02:08:42

问题


I have a stored procedure, GetRegions, which fetches some columns into a cursor like so:

OPEN out_cur FOR
    SELECT id, name, ...
      FROM regions, ...
     WHERE ...

This SP is used all over the place - in places where it will return tens of regions and in places where it will return tens of thousands.

I also have a function, GetRegionPath which gets the "path" of a region. It's a moderately expensive function - there's no problem running it on tens of regions, but on tens of thousands would be unacceptable.

I need to write a stored procedure, GetRegionsWithPaths, that gets regions with exactly the same logic, now and forever as GetRegions, but which includes the path of a region in the result set.

At the moment, GetRegionsWithPaths is an exact copy of GetRegions, with the addition of the path:

OPEN out_cur FOR
    SELECT id, name, ..., GetRegionPath(id) path
      FROM regions, ...
     WHERE ...

but that's not acceptable - if someone edits GetRegions then the two SPs will be out of sync. What I'd like is to take the cursor from GetRegions and then add the path to it. Something like:

GetRegions(..., v_cur);

OPEN out_cur FOR
    SELECT id, name, ..., GetRegionPath(id) path
        FROM ( SELECT * FROM v_cur );

Is this possible? If so, what's the syntax?


回答1:


One possible solution (that could eventually be simplified) is to use a table function to process the cursor and to add the function value.

Assume the function returning the sys_refcursor is called get_cur and that the cursor consist of column ID, NAME (this is important, as the table function requires type definition).

You declare the TYPE for the row (including the additional path column) and for the resulting table.

create type t_row is object
 ( id             number(10),
   name varchar2(10),
   path varchar2(10)
);
/

create type t_rows is table of t_row;
/

and define the table function fetching the cursor and adding the function call.

create or replace function get_cur2  return 
t_rows
PIPELINED
as
   cv_out     sys_refcursor;
   id   number;
   name   varchar2(100);    
begin
      cv_out := get_cur; 
      loop 
        FETCH cv_out INTO id, name;
        exit when cv_out%NOTFOUND;
        pipe row(t_row(id,name, GetRegionPath(id)));
      end loop;
      close    cv_out;
      return;
end;
/

Now you may select the data from the table function

select * from  table(get_cur2); 

        ID NAME       PATH     
---------- ---------- ----------
         1 one        path 1     
         2 two        path 2 

and of course you may use this query to open a cursor in a third function that will return the SYS_REFCURSOR with the additional path column.




回答2:


Alternative implementation using the parameter proposed in the comments.

Suppose the original function looks like this

create or replace function get_cur return SYS_REFCURSOR is
cv_out     sys_refcursor;
begin
 OPEN cv_out  
      FOR 
      select   Id,   name from tab;
 return cv_out;
end;
/

You add a parameter return_path which is either 0 - which returns the original cursor or 1 - which will return the original curosr with the path column.

The implementation could be like this

create or replace function get_cur_with_param(return_path NUMBER) return SYS_REFCURSOR is
cv_out     sys_refcursor;
v_stmt_str      VARCHAR2(4000);
begin
 v_stmt_str := 'select   Id,   name '||case when return_path = 1 then ', GetRegionPath(id)' end ||' from tab';
 OPEN cv_out  FOR v_stmt_str; 
 return cv_out;
end;
/

than get_cur_with_param(0) returns the 2 column cursor and get_cur_with_param(1) returns the cursor with the path column added.

Note that the SQL is build dynamically, but will end only with two variants, so this will be no problem for parsing. If you have additional parameters in the query use bind variables adding the USING clause.



来源:https://stackoverflow.com/questions/35485415/how-do-i-write-a-stored-procedure-which-adds-a-column-to-a-ref-cursor-from-anoth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!