|
Replies:
30
-
Pages:
3
[
1
2
3
| Next
]
-
Last Post:
Aug 14, 2007 1:18 PM
Last Post By: Jornica
|
|
|
Posts:
21
Registered:
12/08/06
|
|
|
|
Calling a procedure dynamically
Posted:
Jun 5, 2007 2:19 AM
|
|
|
|
Suppose that a_function_name returns an integer.
I want to do something like :
EXECUTE IMMEDIATE 'package_name.proc_name(a_function_name)';
I need this to remove code duplication dramatically.
EXECUTE IMMEDIATE says that this is not valid SQL. If EXECUTE IMMEDIATE cannot execute PL/SQL than do I need something else? I have a procedure name at runtime and want to call it. Is it possible?
Thank you.
|
|
|
Posts:
1,851
Registered:
12/18/00
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 2:22 AM
in response to: toltec
|
|
|
|
Why Dynamic SQL ? Why not simply
begin
package_name.proc_name(a_function_name);
end;
/
?
Rgds.
|
|
|
Posts:
21
Registered:
12/08/06
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 2:36 AM
in response to: dnikiforov
|
|
|
The procedure that uses the dynamic-sql gets the procedure name to call as a parameter:
PROCEDURE my_procedure(procedure_call varchar2) IS
BEGIN
EXECUTE IMMEDIATE procedure_call;
END;
This is exactly what I need to do.
my_procedure will be a template-like method which does the common actions and calls the procedure which different clients pass as a parameter. I don't know if there is a tool like "function pointer" in PL/SQL. But it seems "execute immediate" cannot be used that way.
|
|
|
Posts:
3,447
Registered:
04/03/06
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 2:43 AM
in response to: toltec
|
|
|
try...
PROCEDURE my_procedure(procedure_call varchar2) IS
BEGIN
EXECUTE IMMEDIATE 'begin '||procedure_call||'; end;' ;
END;
|
|
|
Posts:
892
Registered:
11/28/06
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 2:45 AM
in response to: toltec
|
|
|
|
Hi,
Simply calling the procedure should do the task.
PROCEDURE my_procedure(procedure_call varchar2) IS
BEGIN
procedure_call;
END;
Just Try out.
Regards.
|
|
|
Posts:
1,851
Registered:
12/18/00
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 2:47 AM
in response to: toltec
|
|
|
The procedure that uses the dynamic-sql gets the procedure name to call as a
parameter
PROCEDURE my_procedure(procedure_call varchar2) IS
BEGIN
EXECUTE IMMEDIATE procedure_call;
This sounds like a really poor design. Procedures, functions and packages are
the programming interface which is limited by the business rules.
Your different clients have to get the access to strongly defined and limited interface. What you do is knows as "SQL injection" and and the huge hole in the
security system - your clients will be able to do anything in the system, if
you provide them with this code. Such approach is definitly wrong and has to be gone.
Rgds.
|
|
|
Posts:
1,851
Registered:
12/18/00
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 2:48 AM
in response to: AJR
|
|
|
Simply calling the procedure should do the task.
PROCEDURE my_procedure(procedure_call varchar2) IS
BEGIN
It is wrong.
Simply check your advise before post, please.
Rgds.
|
|
|
Posts:
8,624
Registered:
05/27/99
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 3:32 AM
in response to: toltec
|
|
|
|
> But it seems "execute immediate" cannot be used that way.
It can.. but you are calling the SQL engine and parser and not the PL/SQL engine and parser.
As the other guys showed, you need to create an anonymous PL/SQL block (using BEGIN and END tags) in order to call the PL/SQL engine.
But there is a problem with this approach - variables. How do you intend to pass parameters to the dynamic procedure being called?
Anonymous PL/SQL blocks wind up in the Oracle Shared Pool. If you do not use bind variables, then 100's of these can have a big performance impact on Oracle.. and lead to shared pool fragmentation and resulting memory allocation errors.
So bind variables is not just a Good Idea.. but kind of mandatory. But using bind variables with dynamic procedure calls.. that gets quite complex to code, maintain and debug.
I also question this design approach of yours. The caller knows what procedure to call, right? After all, it passes the actual name to call to your sample MY_PROCEDURE proc.
So if the caller knows what it wants to call, why not simply call it directly?
It is really not a sensible approach. (the one you proposes)
A truly dynamic system will be one where the caller does not know who to call. For example. The caller sends a message saying "I need ABC done please". This message is dequeued and message processing system will call proc A1 to do A and proc F10 to do B and C.
I do not see anything vaguely like this in the approach your proposing to use.. which in my mind raise numerous questions as to how sound your approach is.
|
|
|
Posts:
21
Registered:
12/08/06
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 4:08 AM
in response to: dnikiforov
|
|
|
EXECUTE IMMEDIATE 'BEGIN proc; END;'
works just fine.
This sounds like a really poor design. Procedures, functions and packages are
the programming interface which is limited by the business rules.
Your different clients have to get the access to strongly defined and limited >>interface. What you do is knows as "SQL injection" and and the huge hole in >>the
security system - your clients will be able to do anything in the system, if
you provide them with this code. Such approach is definitly wrong and has to >>be gone.
My intention was to use this feature on test procedures that exercise existing stored procedures. When the test fixtures became complex, code duplication became apperant.
No clients (as you mean) are going to call these sp's. Interface is limited to unit test procedures. In other words these are not going to be released.
What I can criticize is that there is too much logic in PL/SQL codes so I needed to write unit tests. My favorite approach would be to use SQL only for CRUD and just test CRUD behaviour.
|
|
|
Posts:
21
Registered:
12/08/06
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 4:26 AM
in response to: Billy Verreynne
|
|
|
It can.. but you are calling the SQL engine and parser and not the PL/SQL engine and parser.
I understand. This is what I've been missing.
I also question this design approach of yours. The caller knows what procedure >to call, right? After all, it passes the actual name to call to your sample >MY_PROCEDURE proc.
Consider this procedure:
PROCEDURE my_procedure(proc_to_call varchar2) IS
BEGIN
-- Some common tasks
-- ...
EXECUTE IMMEDIATE ' BEGIN ' || proc_to_call || '; END;';
-- Other common tasks
END;
I'm planning to write several test procedures that share the common tasks mentioned above. But if I call the "procedure_to_call" directly, I have to write the common task codes for each procedure. My intention was to remove that duplication. Is is still a bad approach?
A truly dynamic system will be one where the caller does not know who to call.
In the procedure above the client doesn't have to know what procedure to call I think. Maybe the client reads the procedure name from a config file and calls it etc. No?
|
|
|
Posts:
8,624
Registered:
05/27/99
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 4:54 AM
in response to: toltec
|
|
|
> Consider this procedure:
Ah.. you are talking about creating a test harness. For example, the client application will typically make an application logon call (setting up a context for example to enable FGAC), set NLS settings and so on - and only then make a application process call to a specific procedure.
You want to test those procedures from a "pretend client" and needs to go through all those setups first before making the call.
Hmmm... yes, I can see why you want to use this approach. And if this is specifically going to do the job for you, I do not see why specifically you should not use this approach.
Practical experience tells me however that a test harness is never this simple and easy.
In today's development paradigm (XP/agile/etc), a great deal of emphasis is placed on test cases. And actually coding these test cases as units.
This is different as your approach seems to me to simply test a single procedure in isolation. Which is fine to simply validate the basics for that procedure - but for the business process.
I prefer to write my test cases as complete end-to-end unit tests of a business process. Something along the lines of:
create or replace procedure TestInvoiceRun is
begin
TestHarness.ClientLogon;
TestHarness.DoCommonStuff;
-- starting invoice process
ProcA;
TestHarness.EvaluateA;
ProcB;
TestHarness.EvaluateB;
.. etc.
-- process completed
TestHarness.EvaluateInvoice;
exception when OTHERS then
TestHarness.DumpState;
raise;
end;
And then have a similiar test procedures/packages for stock orders, shipping orders, etc - whatever test cases demand.
|
|
|
Posts:
21
Registered:
12/08/06
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 5:35 AM
in response to: Billy Verreynne
|
|
|
Yes, that's what I'm trying to do exactly: Black box tests..
In today's development paradigm (XP/agile/etc), a great deal of emphasis is >placed on test cases. And actually coding these test cases as units.
This is different as your approach seems to me to simply test a single procedure >in isolation. Which is fine to simply validate the basics for that procedure - but for >the business process.
But PL/SQL is not the right place to do this I think. Complex logic in stored procedures caused that. And that procedures are not formed in an object oriented fashion which makes them hard to test.
Using mock objects and stubs are easy in object oriented environments but not here. So I just preferred a non-complete black box approach.
I see that, object oriented approaches encourage object to relational mapping and no business logic stored in the database. Than all you need is CRUD SQL and all you need to test is CRUD.
I hope object oriented databases will be used widely which will make it very easier to think in terms of objects. I wonder if Oracle is planning to make investment on object oriented database technology.
|
|
|
Posts:
892
Registered:
11/28/06
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 5:49 AM
in response to: dnikiforov
|
|
|
Hi dnikiforov ,
I misunderstood the question. i meant
SQL*Plus: Release 9.0.1.0.1 - Production on Tue Jun 5 18:14:38 2007
(c) Copyright 2001 Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
SQL> create or replace procedure proc1
2 is
3 begin
4 dbms_output.put_line('Inside Proc1');
5 end;
6 /
Procedure created.
SQL> create or replace procedure proc2
2 is
3 begin
4 dbms_output.put_line('Inside Proc2');
5 dbms_output.put_line('calling proc1');
6 proc1;
7 end;
8 /
Procedure created.
SQL> set serveroutput on;
SQL> execute proc2;
Inside Proc2
calling proc1
Inside Proc1
PL/SQL procedure successfully completed.
SQL>
Regards.
|
|
|
Posts:
892
Registered:
11/28/06
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 6:12 AM
in response to: AJR
|
|
|
Hi,
SQL> CREATE OR REPLACE procedure proc2(procname in varchar2)
2 is
3 begin
4 dbms_output.put_line('Inside Proc2');
5 dbms_output.put_line('calling proc1');
6
7 BEGIN
8 EXECUTE IMMEDIATE 'begin '||procname||'; end;';
9 End;
10
11 End;
12 /
Procedure created.
SQL> execute proc2(proc1);
BEGIN proc2(proc1); END;
*
ERROR at line 1:
ORA-06550: line 1, column 13:
PLS-00222: no function with name 'PROC1' exists in this scope
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
SQL> execute proc2('proc1');
Inside Proc2
calling proc1
Inside Proc1
PL/SQL procedure successfully completed.
SQL>
Regards.
|
|
|
Posts:
8,624
Registered:
05/27/99
|
|
|
|
Re: Calling a procedure dynamically
Posted:
Jun 5, 2007 10:13 PM
in response to: toltec
|
|
|
> But PL/SQL is not the right place to do this I think.
PL/SQL can do everything you can do in Java. My entire application tier is PL/SQL and resides in Oracle.
My systems do not use Java at all - except for the odd Java stored proc. The J2EE guys we have, have now too begun to code 90% of their applications in PL/SQL, only using Java to do the rendering. They use JBoss for rendering. I use APEX.
> Complex logic in stored procedures caused that. And that procedures are
not formed in an object oriented fashion which makes them hard to test.
That is the choice you as developer make - how to use PL/SQL. It does support o-o.
And alluding that procedural code is more difficult to test than o-o code.. I differ on that. In fact, o-o has a lot more hidden complexities that one does not have with procedural code.
> I see that, object oriented approaches encourage object to relational
mapping and no business logic stored in the database. Than all you need is
CRUD SQL and all you need to test is CRUD.
Utter bs. That is the single primary reason for the failure of so many systems. The database is not a bit bucket. And J2EE is a failure because of this bit bucket approach.
If you only need a persistence layer for app code, then a RDBMS is not needed. Especially not Oracle.
But you do need a database. Why? Because the app server is incapable of being a database as good as what the database tier is.
What I really do not understand is that people who are o-o schooled, should be the very first to realise the benefits of importance of the data, the importance of encapsulating code with data - and yet, design the application in one tier and wants the data in another tier.
Fact is that PL/SQL is even more capable than Java or .Net in this regard. Fact is that Oracle is not just a bit bucket, but the most advance RDBMS product on this planet and very capable of encapsulating the COMPLETE app tier.
Fact is, it does this cheaper and faster and more scalable than an app server.
And ignoring these facts is why the majority of J2EE systems are failures at the end of the day.
|
|
|
|
Legend
|
|
Guru : 2500
- 1000000
pts
|
|
Expert : 1000
- 2499
pts
|
|
Pro : 500
- 999
pts
|
|
Journeyman : 200
- 499
pts
|
|
Newbie : 0
- 199
pts
|
|
Oracle ACE Director
|
|
Oracle ACE Member
|
|
Oracle Employee ACE
|
|
Helpful Answer
(5 pts)
|
|
Correct Answer
(10 pts)
|
|