Skip to Main Content
  • Questions
  • using PL/SQL in the using clause of Execute Immediate.

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Angelo.

Asked: January 02, 2001 - 3:32 pm UTC

Last updated: August 13, 2004 - 4:51 pm UTC

Version: 8.1.5

Viewed 1000+ times

You Asked

Dear Tom,

What I am trying to do is collect a number of elements into a PL/SQL table, can i pass this table as an OUT variable in the EXECUTE IMMEDIATE with a USING clause. My PL/SQL table definition is defined in a package spec as follows:

type v_event_table is table of incident_event.event_id%type;

type v_event_rec is record
(event_id_data v_event_table,
idx binary_integer := 0);

I want to pass back the event_id(of which there can be many) once I find the host database where the reside by using the following.

t_call := 'rpc_inc_events._rpc_inc_evt@' ||
t_accryn '.WORLD:1, :2, :3, :4, :5, :6, :7)';

EXECUTE IMMEDIATE 'BEGIN ' || t_call ||'; end;'
USING IN OUT t_incident_id,
IN OUT t_notes,
IN OUT t_asset,
IN OUT t_status,
IN OUT t_impact_sum,
IN OUT t_countermeasures,
OUT t_event_rec)
t_event_rec is defined in the parameter list of the procedure as type v_event_rec.


and Tom said...

No, you will find passing the plsql tables back and forth to be pretty much impossible.


In order to even send the table over to the remote procedure, the local variable t_event_rec MUST be defined as:


t_event_rec rpc_inc_events.v_event_table@databaselink;


you see -- in order to call rpc_inc_events.rpc_inc_evt you MUST use the same exact type (not another type that is defined the same) or you will recieve an error. A static example will demonstrate this:

At the remote site I have:

reate or replace package my_pkg
as
type myArray is table of varchar2(255) index by binary_integer;

procedure foo( x in out int, y in out myArray );
end;
/


Locally I tried:


scott@ORA8I.WORLD> declare
2 type myArray is table of varchar2(255) index by binary_integer;
3 t_x number default 4;
4 t_y myArray;
5 begin
6 my_pkg.foo@ora816dev.us.oracle.com( t_x, t_y );
7 end;
8 /
declare
*
ERROR at line 1:
ORA-06550: line 6, column 2:
PLS-00306: wrong number or types of arguments in call to 'FOO'
ORA-06550: line 6, column 2:
PL/SQL: Statement ignored


scott@ORA8I.WORLD>
scott@ORA8I.WORLD> declare
2 t_x number default 4;
3 t_y my_pkg.myArray@ora816dev.us.oracle.com;
4 begin
5 my_pkg.foo@ora816dev.us.oracle.com( t_x, t_y );
6 end;
7 /

PL/SQL procedure successfully completed.

See, I have to use the REMOTE type in order to call this remote procedure. Here in lies your problem -- you are choosing the database link dynamically, you must define your variables statically! You cannot possibly "use" the correct type.

In addition to that, execute immediate accepts only SQL types in the USING section. You cannot have plsql types in there. If you try to use SQL types (create type....) you run into the same problem above -- you have to use the REMOTE sql type but that would be static (and doesn't even work, you cannot use a remote SQL type) again, not dynamic.


Rating

  (5 ratings)

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

Comments

ORA-04054

Bipin Ganar, August 04, 2003 - 9:24 am UTC

Hi Tom,
I have created one package to copy the data from one database to another with databaselink but as one of databaselink is not working it is giving me directly error ORA-04054.

Create or replace package package1 as

procedure p_mv_data(i_data_push_id in varchar2) is

lv_dest_br varchar2(100);
sql_stmnt_pushcntrl varchar2(1000);
sql_stmnt_pushdata varchar2(1000);
lv_data_pushid varchar2(30);
lv_sqlcode number;
lv_sqlerrm varchar2(200);
dblink_not_found exception;
pragma exception_init(dblink_not_found,-04054);
begin

lv_data_pushid :=i_data_push_id;

select '@'||service_name||'.world'
into lv_dest_br
from schema1.push_control,schema1.networked_branches
where to_number(destination_db)=br_cd
and data_push_id=lv_data_pushid;

sql_stmnt_pushdata:='insert
into schema3.push_data'||''||lv_dest_br||''||
' select b.col1,b.col2,b.col3,b.col4,b.col5,b.col6,b.col7,
b.col8,b.col9,b.col10,b.col11,b.col12,b.col13,b.col14,b.col15,b.col16,b.col17,b.col18,b.col19,
b.col20,b.col21,b.col22,b.col23,b.col24,b.col25,b.col26,b.col27,b.col28,b.col29,b.col30
from schema2.push_control a ,schema2.push_data b
where a.data_push_id ='||''''||lv_data_pushid||''''||
' and a.data_push_id=b.data_push_id;


EXECUTE IMMEDIATE sql_stmnt_pushdata;

commit;

exception

when dblink_not_found then
RAISE_APPLICATION_ERROR(-04054,'error');

insert into datacopy.pushstring values(sql_stmnt_pushdata);

when others
lv_sqlcode:=sqlcode;
lv_sqlerrm :=sqlerrm;

dbms_job.isubmit(v_job_no,v_task,sysdate,null);

commit;
end p_mv_data;
end package1;

Can u tell me how to handle such error ?
as procedure is getting successfully completed then i 'm not able to trace which of the link is not working .
Although if it's not working it should go for the next dblinks and insert the data.

Tom Kyte
August 04, 2003 - 10:17 am UTC

I do not think you've given us the whole story here.

that error is raised upon COMPILATION, not execution of the block of code.

I fail to see how this example would do that. it seems the script that is invoking this is using a dblink and that script is what is failing to compile.


you might see this at runtime IF you were compiling an anonymous block of PLSQL -- which are you not. Then it should be catchable.

sumam seth, August 04, 2003 - 11:43 pm UTC

I've tested the same what you have mentioned in your answer,when iam using a anonymous block it throws the exception ,how do i handle that exception in my program,as if u see the pkg.procedure p_mv_data, when the database link fails it never goes in to the exception part.
My objective here is to handle the pl/sql compilation exceptions thru my program.



Tom Kyte
August 05, 2003 - 7:10 am UTC

give me a concrete working example to demonstrate with.

Lolita, August 13, 2004 - 9:23 am UTC

What is the maximum number of rows or maximum size of a PL/SQL table that can be pass thru a database link. I have successfully tried passing 145 rows 4 bytes each but more than that I'm getting the catch all error 'eof of communication channel error' How can I work around with this limitation?

Tom Kyte
August 13, 2004 - 4:51 pm UTC

there is no defined limit, if you are hitting a 3113, that would necessitate a tar.

Lolita, August 13, 2004 - 9:24 am UTC

What is the maximum number of rows or maximum size of a PL/SQL table that can be pass thru a database link. I have successfully tried passing 145 rows 4 bytes each but more than that I'm getting the catch all error 'eof of communication channel error' How can I work around with this limitation?

using PL/SQL in the using clause of Execute Immediate

Lolita, August 13, 2004 - 9:24 am UTC

What is the maximum number of rows or maximum size of a PL/SQL table that can be pass thru a database link. I have successfully tried passing 145 rows 4 bytes each but more than that I'm getting the catch all error 'eof of communication channel error' How can I work around with this limitation?

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