Remote Pipeline or Remote sys_refcursor [message #565470] |
Tue, 04 September 2012 11:47  |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
Is there any way to return a result set (using a Database Link) from one Database to another Database? Database A needs to call Database B and Database B needs to return a result set via a stored package/function. The stored procedure/function on Database B also accepts 1 input parameter. Something like "select test.test('some input parameter')@database_b from dual'.
Any ideas or is this something Oracle just can not do?
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565483 is a reply to message #565480] |
Tue, 04 September 2012 12:39   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
I don't believe that works. The syntax may be correct and the SQL statement does execute on the remote database but there are no results. Taking the same SQL statement and running it on the local database returns a result set. I'm using Toad and the remote database gives me an error of "Cursor must be opened".
|
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565487 is a reply to message #565485] |
Tue, 04 September 2012 13:02   |
John Watson
Messages: 8974 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
what's the problem?orcl>
orcl> create database link l1 connect to scott identified by tiger using 'orcl';
Database link created.
orcl> create function dname (dno number) return varchar2 as
2 vdname varchar2(20);
3 begin
4 select dname into vdname from dept where deptno=dno;
5 return vdname;
6 end;
7 /
Function created.
orcl> select dname@l1(10) from dual;
DNAME@L1(10)
---------------------------------------------------------------------------------------
ACCOUNTING
orcl>
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565489 is a reply to message #565488] |
Tue, 04 September 2012 13:10   |
John Watson
Messages: 8974 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
Ah, I think I see the problem, is this it?orcl> create or replace type num_tab as table of number;
2
3
4 /
Type created.
orcl> create or replace function transform(depts in sys_refcursor)
2 return num_tab
3 pipelined
4 is
5 no number;
6 begin
7 loop
8 fetch depts into no;
9 exit when depts%notfound;
10 no:=no * 10;
11 pipe row(no);
12 end loop;
13 return;
14 end;
15 /
Function created.
orcl> select * from table(transform@l1(cursor(select deptno from scott.dept)));
select * from table(transform@l1(cursor(select deptno from scott.dept)))
*
ERROR at line 1:
ORA-30626: function/procedure parameters of remote object types are not supported
orcl>
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565491 is a reply to message #565490] |
Tue, 04 September 2012 13:18   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
That would be it.
Michel,
I've tried the Pipelined function but I can't get it to work either. Do you have any examples? Remember, I'm trying to pass in a value and return a result set. Something like this select test.test@database_b('some input parameter') from dual; from Database A that is calling Database B. Just Oracle calling Oracle. You would think Oracle could easily do this.
[Updated on: Tue, 04 September 2012 13:20] Report message to a moderator
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565493 is a reply to message #565491] |
Tue, 04 September 2012 13:53   |
John Watson
Messages: 8974 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
Just one last suggestion: can you create a view that uses the function without the parameter, and then query the view through the dblink with a predicate? Could that give you the desired result?
Probably no good, but it is all I can think of.
|
|
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565501 is a reply to message #565497] |
Tue, 04 September 2012 15:23   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
Ok, here goes.
Oracle A needs to receive a result set from Oracle B based on 1 input parameter to the Package/Function. Oracle B has a package that accepts one parameter and returns a sys_refcursor. Oracle A calls Oracle B using a select statement using a Database Link.
Things I've tried:
1). Package/Function accepting 1 parameter and returning a sys_refcursor (as Michel has pointed out, this will not work. Oracle limitation.)
2). Package/Function accepting 1 parameter and returning a pipelined record. This will work if a view is created on the remote Database (Oracle B) and Oracle A calling that View using a simple select * name_of_view@database_link
2 a). No way to pass an input parameter to the view. If the Package/Function returns information about states, how do I just limit the result set to Missouri?
3). Oracle A is only using simple SQL select statements to retrieve the results.
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565504 is a reply to message #565501] |
Tue, 04 September 2012 16:09   |
John Watson
Messages: 8974 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
I think I understand the issue, which is architectural, to do with passing parameters by value or reference. Passing a reference through a db link from B to A would be useless, because it wouldn't refer to anything. A function such as that I gave first returns a value, so no problem. But cursor variables (this is in the docs) are always passed by reference, which is why my pipelined function fails. Sensible: a cursor might be zillions of rows, you wouldn't want to evaluate it and pass it by value.
So you can't return a cursor through the db link. What can you do? I think you have to do all the work in your database A. Perhaps create a view(s) populated from B through a link, and run the function in A against the view? Building on my previous example,orcl> create view dept_view as select * from dept@l1;
View created.
orcl> select * from table(transform@l1(cursor(select deptno from scott.dept)));
select * from table(transform@l1(cursor(select deptno from scott.dept)))
*
ERROR at line 1:
ORA-30626: function/procedure parameters of remote object types are not supported
orcl> select * from table(transform(cursor(select deptno from scott.dept_view)));
COLUMN_VALUE
------------
100
200
300
400
orcl> How's that?
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565505 is a reply to message #565504] |
Tue, 04 September 2012 16:36   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
If I follow you correctly (and I'm probably not) then I don't think that will work. The Package/Function on Oracle B (remote database) accepts one parameter. This could be 'A', 'B', 'C', 'D'....etc and returns a result set based on that input. So if the input is 'A' then the Package/Function would return every company beginning with the letter A.
I can create a view on Oracle B that calls the Package/Function on that database. Oracle A does a SQL select statement using a database link to call the view on Oracle B but how do I pass in 'A', 'b', 'C', 'D'...etc.
Not sure if that helps or not. I'm probably not explaining myself very clearly.
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565534 is a reply to message #565513] |
Wed, 05 September 2012 02:58   |
mnitu
Messages: 159 Registered: February 2008 Location: Reims
|
Senior Member |
|
|
I think that the parameter value could be injected into the remote pipelined procedure by using a context. This is almost the same solution as Michel showed but there are some nuances that can matter.
|
|
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565551 is a reply to message #565539] |
Wed, 05 September 2012 04:08   |
mnitu
Messages: 159 Registered: February 2008 Location: Reims
|
Senior Member |
|
|
Base 1
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.4.0
Connected as mni
SQL>
SQL> Create Or Replace Type t_scalaire As Object (
2 id integer,
3 Val varchar2(10)
4 )
5 /
Type created
SQL> Create Or Replace Type t_nt As Table Of t_scalaire
2 /
Type created
SQL> Create Context t_ctx using aPkg
2 /
Context created
SQL> Create Or Replace Package aPkg Is
2 Procedure SetCtx (
3 value Varchar2
4 );
5 End;
6 /
Package created
SQL> Create Or Replace Package Body aPkg Is
2 Procedure SetCtx (
3 value Varchar2
4 ) Is
5 Begin
6 DBMS_SESSION.set_context('t_ctx', 'val', value);
7 End;
8 End;
9 /
Package body created
SQL> Create Or Replace Function Get_T_Data Return t_nt Pipelined Is
2 Begin
3 For rec In (Select * From t Where val = sys_context('t_ctx','val'))
4 Loop
5 Pipe row(t_scalaire(rec.id, rec.val));
6 End Loop;
7 --
8 Return;
9 End;
10 /
Function created
SQL> Create View t_v (id, val) As
2 Select *
3 From table(get_t_data())
4 /
View created
SQL>
Base 2
Connecté à :
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> exec aPkg.SetCtx@adb('A');
Procédure PL/SQL terminée avec succès.
SQL> select * from t_v@adb
2 /
ID VAL
---------- ----------
3 A
6 A
9 A
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565622 is a reply to message #565559] |
Wed, 05 September 2012 11:36   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
Trying to wrap my head around all the examples. So, you can pass a variable but it might not be safe to do it? This would also require me to execute 2 SQL statements to accomplish my goal? Could information get mixed up? Two people at almost the same time with one passing a value of 'A' and the other passing the value of 'B' and the first person would see the results of the value 'B' versus seeing the results of 'A'. I would not want that situation. Not sure if that is even possible.
|
|
|
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565745 is a reply to message #565721] |
Thu, 06 September 2012 08:49   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
I've never done a web service that PL/SQL can read. For now, I have a job that runs three times a day on Oracle B that populates a table and then Oracle A just reads that table via a database link. I don't really care for this but it gets the job done. I really wanted the process to be more dynamic, in that, the call to Oracle B from Oracle A would be dynamic in looking up the information versus having the information static in a table.
I've always wanted to ask this question and since the discussion of pipelined functions came up in this thread. Will a sys_refcursor be faster than using a pipelined function to return data? In other words, if you have an application that needs to read a result set, you should always return a sys_refcursor to the calling application. This assumes that the application can read a sys_refcursor which I believe most do.
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565748 is a reply to message #565746] |
Thu, 06 September 2012 09:02   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
Sorry, I wasn't clear. I can and I do use a sys_refcursor. Since reading up on pipelined functions I just wondered if using a pipelined function was faster than using s sys_refcursor. I would so no but that's why I'm asking.
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565749 is a reply to message #565748] |
Thu, 06 September 2012 09:07   |
John Watson
Messages: 8974 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
I've used pipelined functions in ETL processing. By piping the rows from one process to another as they are generated, multiple processes (such as the E, the T and the L) can run concurrently. Much faster than having to wait for one step to complete before starting the next. By contrast, I think a function returning a ref cursor has to run to completion before the cursor can be returned. So even though the ref cursor approach might be faster if you are doing only one thing, you don't get the benefit of operations running concurrently.
I am course open to correction on this.
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565750 is a reply to message #565748] |
Thu, 06 September 2012 09:15   |
mnitu
Messages: 159 Registered: February 2008 Location: Reims
|
Senior Member |
|
|
I'd never tested if returning data via a ref cursor is faster than via a pipelined function but we can agree without doing any test that's much simpler. Pipeline function exists in order to transform the (returned) data.
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565751 is a reply to message #565749] |
Thu, 06 September 2012 09:21   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
That's my understanding of the pipelined process also. That's why I asked the question. For a web application, would it work the same way, meaning, would the browser start displaying the information right away using a pipelined function versus waiting for the whole result set for a sys_refcursor? If your PL/SQL code returned all the companies in the United States starting with 'A' would you start to see 1 to 3 rows of data within the browser using the pipelined function versus the browser just sitting there until all the records could be displayed?
[Updated on: Thu, 06 September 2012 09:26] Report message to a moderator
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565757 is a reply to message #565755] |
Thu, 06 September 2012 10:01   |
John Watson
Messages: 8974 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
Mnitu, my pl/sql knowledge is pretty bad, so I may well be wrong. Try this:create or replace type nums as table of number;
/
create or replace function pipenums
return nums
pipelined
as
begin
for i in 1..30 loop
pipe row(i);
dbms_lock.sleep(1);
end loop;
end;
/
set arraysize 1
select * from table(pipenums); Is it possible to get the same effect without a pipeline? The first row immediately, and then one row per second? Duane, is that the sort of thing you are thinking of?
|
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565763 is a reply to message #565757] |
Thu, 06 September 2012 10:28   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
Not really. Most web applications will not display the results until all the results are there to display. I'm sure I'm not explaining myself correctly. Just envision a web application that displays a report with a spinning icon and the spinning icon doesn't go away until all the results are shown. Given the same example, the spinning icon would go away almost immediately with the pipelined function because the first record would display and then when more records showed up they would display. Maybe that doesn't make any sense at all.
|
|
|
Re: Remote Pipeline or Remote sys_refcursor [message #565771 is a reply to message #565760] |
Thu, 06 September 2012 10:53   |
Duane
Messages: 585 Registered: December 2002
|
Senior Member |
|
|
Michel Cadot wrote on Thu, 06 September 2012 10:24No, it's me, I was not clear, I was going back to your initial question and ask if you can't from your application open a connection to the other (remote) database and directly get the result from it instead of getting through a db link.
For the initial problem, it's just Oracle A talking to Oracle B. Oracle B has a Pl/SQL package/function that accepts one input parameter (student id) and then returns some information for that student back to Oracle A for display. Oracle A is our PeopleSoft Portal and Oracle B contains some information about a student (taken an exam, filled out a survey...etc), so, I was trying to get that information from Oracle B back to Oracle A to display on the portal without having to read a simple static table. I wanted the information about the student to be more dynamic on the Portal (show a link to take a test...once the test has been taken...then remove the link). With the table I can show the link but once they take the test the link is not removed until the table is updated again.
My packages could live on Oracle A (PeopleSoft Portal) and read the tables on Oracle B via a database link but then we don't control Oracle A. It's like buying gas and you can only get the gas pumped if the corporation sends out someone to pump the gas and they will only send someone out when you are there by the pump and call. Of course, the corporation is in NY and you live in FL and you have to wait on them.
|
|
|