Skip to Main Content
  • Questions
  • how to dynamically generate cursors with table names that come from parameters.

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question.

Asked: November 12, 2008 - 5:34 pm UTC

Last updated: November 25, 2008 - 2:12 pm UTC

Version: 9

Viewed 1000+ times

You Asked

I am a java developer but I've given a request to generate several 1800 bytes fixed length files, which have the same format but are only different on the select query. As the format keeps changing I though that the best way to generate them is writing pl/sql to create/drop the tables as needed and put the procedures on a package body and definition.

For this, I need to be able to pass the table name as parameter of the procedures as each different results table will generate different a different file. I have been unable to dinamically generate a cursor with the table_name parameter.

After a lot of syntax errors, I've finally been able to write a test function that compiles, but gives me a runtime value_error which I do not know how to fix.
I thought that it is time to ask the experts what would it be the best way to tackle a problem like this one. Any suggestion I will really appreciate it.


CREATE OR REPLACE PROCEDURE populate_email(p_in_table_name VARCHAR2)
AS
 
 TYPE cur_type IS REF CURSOR;
 tmp_cur cur_type;
 
 TYPE email_rec IS RECORD (
  intid internetaddress.intid%TYPE,
  intaddress internetaddress.intaddress%TYPE); 
 query varchar2(100);
 
 tmp_rec email_rec;
BEGIN
 
 query := 'select i.intid, i.intaddress
 from internetaddress i, '||p_in_table_name ||' b 
 where i.intid = b.id';
 
 OPEN tmp_cur  FOR query;
 LOOP
  FETCH tmp_cur INTO tmp_rec;
  EXIT WHEN tmp_cur%NOTFOUND;
 
  EXECUTE IMMEDIATE
  'update '||p_in_table_name ||' a
  set a.ademal = substr(trim('||tmp_rec.intaddress||'),1,50)
  where a.id = '||tmp_rec.intid;
  

 END LOOP;
 
 EXECUTE IMMEDIATE
 'COMMIT';
 

 CLOSE tmp_cur;
 

END;


and Tom said...

That should just be:

execute immediate '
update (select a.ademal, substr( trim( i.intaddress ) ) intaddress
from ' || dbms_assert.sql_object_name( p_in_table_name ) || ' a,
internetaddress i
where i.intid = a.id )
set ademal = intaddress';


There should be *NO PROCEDURAL CODE*

You just want to update a join!!


there are two many things wrong in your plsql routine to address - the first and foremost being the LACK OF BIND VARIABLES and the possible sql injection you have - dbms_assert addresses the sql injection and since we don't have any procedural code anymore, we are OK on the binds in this case.


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

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