Skip to Main Content
  • Questions
  • Returning result set from stored procedure over a database link

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Paul.

Asked: June 14, 2002 - 10:16 am UTC

Last updated: May 30, 2005 - 8:48 am UTC

Version: 9.2.0

Viewed 10K+ times! This question is

You Asked

Tom

I have a requirement to call a stored procedure, via a database link, which returns several rows comprising several fields of data.
The only method I have been able to succesfully implement is to pass back a PL/SQL table for each field of data. Is there a more elegant solution that I have overlooked in ignorance.

Thanks in advance

Paul

and Tom said...

Hey -- the FIRST 9iR2 question ever!

You can do this:

scott@ORA9I.WORLD> create or replace package my_pkg
2 as
3 type myScalarType is record
4 ( x int, y date, z varchar2(80) );
5
6 type myTableType
7 is table of myScalarType index by binary_integer;
8
9 procedure p( p_data out myTableType );
10 end;
11 /

Package created.


scott@ORA9I.WORLD> create or replace package body my_pkg
2 as
3 function scalarType( x in int, y in date, z in varchar2 )
4 return myScalarType
5 is
6 l_data myScalarType;
7 begin
8 l_data.x := x; l_data.y := y; l_data.z := z;
9 return l_data;
10 end;
11
12 procedure p( p_data out myTableType )
13 is
14 begin
15 for i in 1 .. 5
16 loop
17 p_data(p_data.count+1) := scalarType( i, sysdate+i, 'row ' || i);
18 end loop;
19 end;
20 end;
21 /

Package body created.

on the remote site (p is your procedure, it'll fill up p_data with whatever).

On the "near" end, you would call it like this:

scott@ORA920> declare
2 l_data my_pkg.myTableType@ora9i;
3 begin
4 my_pkg.p@ora9i( l_data );
5 for i in 1 .. l_data.count
6 loop
7 dbms_output.put_line( l_data(i).x );
8 dbms_output.put_line( l_data(i).y );
9 dbms_output.put_line( l_data(i).z );
10 dbms_output.put_line( '-----------------' );
11 end loop;
12 end;
13 /
1
15-JUN-02
row 1
-----------------
2
16-JUN-02
row 2
-----------------
3
17-JUN-02
row 3
-----------------
4
18-JUN-02
row 4
-----------------
5
19-JUN-02
row 5
-----------------

PL/SQL procedure successfully completed.


so you only need one parameter....

Rating

  (7 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Paul Morris, June 17, 2002 - 5:49 am UTC

Thanks Tom, it works a treat, but leaves me slightly confused.
I had previously tried something similar, the difference being that i had not defined my table with the INDEX BY BINARY_INTEGER parameter. Although my Stored procedure worked when called from the same instance, I got an
ORA-03113: end-of-file on communication channel exception raised when calling it remotely. Why does adding the INDEX BY parameter to the table type definition make a difference.

Tom Kyte
June 17, 2002 - 7:43 am UTC

index by binary_integer makes a plsql table type -- the other was a collection. It should not have 3113'ed (that would be most likely a "bug").

SImilar problem (unsolved here)

Peter Korim, August 03, 2002 - 7:41 pm UTC

I need to repeat the described case with use of java stored procedure on the remote site.

near site - oracle 8.1.7.3
remote site oracle 8.1.7.4

i need to pass a collection to remote databases's java stored procedure.

problems:

A remote site
1. 'index by ' type is rejected by compiler of java stored procedure (the plsql procedure dfinition)
2. 'package owned type' is rejected as well

B near site
3. it is allowed only use of package owned type through dblink otherwise compiler reports PLS-00331: illegal reference error.



Passing a refcursor over a database link

Niloufar, January 14, 2003 - 5:23 pm UTC

Tom,

In 9i, could we call a similar procedure to your my_pkg.p procedure over a database link if it returns a refcursor?!

Thanks,
Niloufar

Tom Kyte
January 14, 2003 - 8:35 pm UTC

refcursors do not cross dblink, no. you cannot return a refcursor over a dblink. a refcursor can reference a dblink, but it cannot be returned over one.

Passing back display output

Jeff Westman, June 04, 2004 - 11:13 am UTC

Hi Tom,

I am trying to execute a remote package that does a simple print display. I can't get it to work.  This is what I have:

/**** remote side ****/

CREATE OR REPLACE PACKAGE p
IS
   PROCEDURE ln (val in VARCHAR2);
END;
/
show errors

CREATE OR REPLACE PACKAGE BODY p
IS

   PROCEDURE ln (val in VARCHAR2)
   IS
   BEGIN
      dbms_output.enable (1000000);
      IF length (val) > 255
      THEN
         raise value_error;
      ELSE
         dbms_output.put_line (val);
      END IF;
   EXCEPTION
      WHEN others
      THEN
         dbms_output.put_line (val);
   END;

END;
/
show errors

When I go to run this locally, I don't see my "hello":

/**** local side ****/


SQL> set serveroutput on;
SQL> exec c2a.p.ln@rmsdev06('hello');

PL/SQL procedure successfully completed.

What am I doing wrong???!

Thanks....!   

Jeff 

Tom Kyte
June 04, 2004 - 12:23 pm UTC

it works -- but it wrote to the dbms_output @remote

sqlplus calls dbms_output after running your procedure to get the data that should be printed out -- it is not going to see the data you stuff in the remote package.

You would actually have to code something like:

create synonym rdbms_output for dbms_output@remote;

declare
l_data Rdbms_output.chararr;
l_nlines number;
begin
Rdbms_output.enable;
c2a.p.ln@remote( 'hello' );
Rdbms_output.getLine( l_data, l_nlines );
for i in 1 .. l_nlines
loop
dbms_output.put_line( l_data(i) );
end loop;
end;
/



Is it possible to exec a Remt SP with Collection as in param & sysrefcursor out parm thru dblink?

Anil Bishnoie, April 19, 2005 - 5:24 pm UTC

i have a procedure on remote with signature
REMOTE INSTANCE R1/SCHEMA S1:
Type array_t1 is table of varchar2(255);// can be record also here
 proc(p_array in array_t1 ,out sys_refcursor)
IS
{
..
..
out is populated ....
}
execute is granted on Type and Procedure to B1 . 

LOCAL INSTANCE L1/Schema B1
DBLINK to REMOTE is LNK created using S1 of Remote,
synonym PROC is created for S1.PROC@LNK.
when i describe the type in local
i get the error
SQL> desc S1.arr_t1@LNK
ERROR:
OCI-21700: object does not exist or is marked for delete

 !oerr ora 21700

21700, 00000, "object does not exist or is marked for delete"
// *Cause:  User attempted to perform an inappropriate operation to
//          an object that is non-existent or marked for delete. 
//          Operations such as pinning, deleting and updating cannot be
//          applied to an object that is non-existent or marked for delete.
// *Action: User needs to re-initialize the reference to reference an
//          existent object or the user needs to unmark the object.


Is this possible to execute such type of Remote Proc using collection as in parm and refcursor as out and if yes
what i need to do to resolve the issue above (is it grant or how it can be reinitialized )?
 

Tom Kyte
April 19, 2005 - 7:51 pm UTC

ref cursors cannot go over dblinks at all.

data retrieval through dblinks in Datawarehousing

Neeraj Ranjan Rath,Hyderabad, May 28, 2005 - 4:55 am UTC

Hi Tom,
I am retrieving data to my datawarehosing system from another system through dblink.The volume of data is around 60m per day.It is very time consuming.Please suggest me how i should extract data from another system quickly.
I have tried to export the table of other system to a flat file.Then i ftp that file to my DWH server.Then i tried to put that through sqlldr.But still it taking almost same time.

Thanks in advance

Tom Kyte
May 28, 2005 - 9:19 am UTC

Is that 60meg? what are the real volumes of data here.

unless you are using dialup between the servers, this is something that should be "fast"

but the amount of supplied information isn't sufficient to comment about anything really.

Followup to my last query

Neerajb Ranjan Rath(Hyderabad), May 30, 2005 - 12:23 am UTC

Tom there 60 million records (6000000).....
Please tell me what else you need for ur kindest suggestion.

Thanks Neeraj R Rath


Tom Kyte
May 30, 2005 - 8:48 am UTC

so how fast is slow and what size does 60,000,000 relate to (is that say 600 meg or 60gig or somewhere in between...)

what sort of network do you have between the two.

and do you really need to move 60,000,000 -- no chance of getting "changes only"

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library