Home » SQL & PL/SQL » SQL & PL/SQL » Dynamic Cursor / Dynamic Rowtype ?!?!
icon9.gif  Dynamic Cursor / Dynamic Rowtype ?!?! [message #137013] Mon, 12 September 2005 15:34 Go to next message
akosz
Messages: 2
Registered: September 2005
Junior Member
It may be that my approach to the situation is completely off, but I can't think of any other way to do this in PL/SQL.

THE PROBLEM:
I have a database with 227 tables. Out of those 227, I am only concerned with those whose name doesn't end in '_TYPE'. This leaves 129 tables. Out of those, I only want to deal with the 25 tables containing the column 'CS_ID'.

Once I know what those tables are I want to loop through them and select all rows where the CS_ID matches a parameter called p_cs_id (which is passed in). Eventually I will be inserting these rows into similar tables in another identical database (but I'm nowhere near ready for that part yet).

I'm trying to do this dynamically (ie. not write 25 different statements). There are many reasons for this, reusable code, changing tables, etc.

MY PROPOSED SOLUTION:
I'm trying to use a dynamic cursor to do this. The problem is, I need to FETCH the data into a record/row that matches the table I am selecting from. But the record/row definition changes with every table I select from, so I can't make one static variable declaration. It's like I need a Dynamic ROWTYPE, but I know of no such thing. Here's the code so far:

DECLARE
   col_cnt   PLS_INTEGER;  -- COLUMN COUNT

   p_cs_id   my_case.cs_id%TYPE := &p_cs_id;  -- CASE PARAMETER

   TYPE  TEMPTABLE IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER;  -- TEMPORARY TABLE TYPE

   tTABLES    TEMPTABLE;       -- TEMPORARY TABLE VARIABLE
--   r_temp     tTABLES(i)%ROWTYPE; -- TEMPORARY ROW
   
   TYPE c_type IS REF CURSOR;  -- DYNAMIC CURSOR TYPE
   c_temp  c_type;             -- TEMP DYNAMIC CURSOR
   q_temp  VARCHAR2 (32000);   -- TEMP QUERY STRING

BEGIN

-- GET THE NAMES OF ALL NON-CODE TABLES (THE TABLES THAT DON'T END IN '_TYPE')
SELECT  table_name
BULK COLLECT INTO tTABLES
FROM    all_tables
WHERE   table_name NOT LIKE '%_TYPE'
AND     owner = 'ME';

-- LOOP THRU ALL NON-CODE TABLES
FOR i in tTABLES.first..tTABLES.last LOOP

   -- INITIALIZE COLUMN COUNT TO ZERO
   col_cnt := 0;

   -- MOVE CASE RECORDS

   -- CHECK FOR A COLUMN NAMED 'CS_ID' IN THE CURRENT TABLE (PROD)
   SELECT  COUNT(*)
   INTO    col_cnt
   FROM    ALL_TAB_COLS
   WHERE   TABLE_NAME  = tTABLES(i)
   AND     COLUMN_NAME = 'CS_ID';

   -- IF CS_ID EXISTS IN CURRENT TABLE (PROD)
   IF col_cnt > 0 THEN

      -- SELECT ROWS MATCHING CS_ID FROM *PROD*
      q_temp := 'SELECT * FROM tTABLES(i) WHERE CS_ID = p_cs_id';

      OPEN c_temp FOR q_temp;

      WHILE TRUE LOOP
         FETCH c_temp INTO r_temp;
         EXIT WHEN c_temp%NOTFOUND;
      END LOOP;

      CLOSE c_temp;

      -- DELETE EXISTING ROWS (W/ SAME CS_ID) FROM *TEST*
         -- NOT CODED YET

      -- INSERT ROWS SELECTED INTO *TEST* 
         -- NOT CODED YET

      -- HANDLE ERRORS
         -- NOT CODED YET
         -- ROLLBACK
         -- LOG ERROR
         -- EXIT PROCEDURE

   END IF;

END LOOP;

END;
/
Re: Dynamic Cursor / Dynamic Rowtype ?!?! [message #137014 is a reply to message #137013] Mon, 12 September 2005 15:49 Go to previous messageGo to next message
smartin
Messages: 1803
Registered: March 2005
Location: Jacksonville, Florida
Senior Member
Can you insert the results of your select statement directly into your new table, thus avoiding the need to fetch the data into an intermediary plsql variable (record) in the first place?

Something like insert into new select * from old where old.column = parameter;
Re: Dynamic Cursor / Dynamic Rowtype ?!?! [message #137033 is a reply to message #137013] Mon, 12 September 2005 19:24 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9105
Registered: November 2002
Location: California, USA
Senior Member
The following inserts into a test schema instead of a test database, but you should be able to get the idea. You would just change all reference to test.table_name to table_name@test, assuming your database link is named test.

-- starting data in scott schema:
scott@ORA92> SELECT * FROM scott.tab1_type
  2  /

COL1                   COL2
---------------------- ----------------------
ends in _type          not to be inserted

scott@ORA92> SELECT * FROM scott.tab2
  2  /

COL1                   COL2
---------------------- ----------------------
no cs_id column        not to be inserted

scott@ORA92> SELECT * FROM scott.tab3
  2  /

CS_ID       COL1                   COL2
----------- ---------------------- ----------------------
NO MATCH    does not match p_cs_id not to be inserted

scott@ORA92> SELECT * FROM scott.my_case
  2  /

CS_ID       COL1                   COL2                   COL3
----------- ---------------------- ---------------------- ----------------------
MATCH_VALUE matches p_cs_id        insert this row        1st my_case value
MATCH_VALUE matches p_cs_id        insert this row        2nd my_case value


-- starting data in test schema:
scott@ORA92> SELECT * FROM test.tab1_type
  2  /

no rows selected

scott@ORA92> SELECT * FROM test.tab2
  2  /

no rows selected

scott@ORA92> SELECT * FROM test.tab3
  2  /

no rows selected

scott@ORA92> SELECT * FROM test.my_case
  2  /

CS_ID       COL1                   COL2                   COL3
----------- ---------------------- ---------------------- ----------------------
MATCH_VALUE matches p_cs_id        delete this row        value in test.my_case


-- deletes and inserts:
scott@ORA92> DECLARE
  2    p_cs_id my_case.cs_id%TYPE := '&g_cs_id';
  3  BEGIN
  4    FOR r_tabs IN
  5  	 (SELECT DISTINCT table_name
  6  	  FROM	 user_tab_columns
  7  	  WHERE  table_name NOT LIKE '%_TYPE'
  8  	  AND	 column_name = 'CS_ID')
  9    LOOP
 10  	 EXECUTE IMMEDIATE
 11  	   'DELETE FROM test.' || r_tabs.table_name
 12  	   || ' WHERE cs_id = :b_cs_id'
 13  	   USING p_cs_id;
 14  	 EXECUTE IMMEDIATE
 15  	   'INSERT INTO test.' || r_tabs.table_name
 16  	   || ' SELECT * FROM ' || r_tabs.table_name
 17  	   || ' WHERE  cs_id = :b_cs_id'
 18  	   USING p_cs_id;
 19    END LOOP;
 20  END;
 21  /
Enter value for g_cs_id: MATCH_VALUE
old   2:   p_cs_id my_case.cs_id%TYPE := '&g_cs_id';
new   2:   p_cs_id my_case.cs_id%TYPE := 'MATCH_VALUE';

PL/SQL procedure successfully completed.


-- results in test schema:
scott@ORA92> SELECT * FROM test.tab1_type
  2  /

no rows selected

scott@ORA92> SELECT * FROM test.tab2
  2  /

no rows selected

scott@ORA92> SELECT * FROM test.tab3
  2  /

no rows selected

scott@ORA92> SELECT * FROM test.my_case
  2  /

CS_ID       COL1                   COL2                   COL3
----------- ---------------------- ---------------------- ----------------------
MATCH_VALUE matches p_cs_id        insert this row        1st my_case value
MATCH_VALUE matches p_cs_id        insert this row        2nd my_case value

scott@ORA92>

Re: Dynamic Cursor / Dynamic Rowtype ?!?! [message #137149 is a reply to message #137033] Tue, 13 September 2005 07:53 Go to previous message
akosz
Messages: 2
Registered: September 2005
Junior Member
good call!

that should work beautifully!

akosz
Previous Topic: size procedure parameter
Next Topic: Inconsistent datatypes
Goto Forum:
  


Current Time: Sun Apr 27 13:04:47 CDT 2025