Search code examples
oracle-databaseplsqlnesteddatabase-cursor

Nested Cursors in PL/SQL


I am working with Oracle PL/SQL. I´m trying to define Nested Cursors, which means that the output from the first Cursor should be the input for the second. To be more specific: the first one should store tables with a specific prefix in it. The second one should store all values from an attribute from all the tables which are in the first one.

Here is my code snippet. I hope it makes my problem a little more clear:

DECLARE
    var_table_name  VARCHAR2(30);
    var_dimension_key  VARCHAR2(30);

CURSOR cur_all_dim IS  
    SELECT 
        table_name
        FROM  dba_tables
        WHERE dba_tables.tablespace_name = 'USERS'
        AND dba_tables.owner = 'DWH_CORE'
        AND UPPER (dba_tables.table_name) LIKE ('%DIM%%')
        AND UPPER (dba_tables.table_name) NOT LIKE ('%TEMP%')
        AND UPPER (dba_tables.table_name) NOT LIKE ('%DEBUG%')
        AND UPPER (dba_tables.table_name) NOT LIKE ('%LOG%');

CURSOR cur_dimension_key IS
    SELECT dimension_key FROM var_table_name;


BEGIN
OPEN cur_all_dim;

LOOP
EXIT WHEN cur_all_dim%NOTFOUND;

    FETCH cur_all_dim INTO var_table_name;

    OPEN cur_dimensions_key;
    LOOP
    EXIT WHEN cur_dimensions_key%NOTFOUND;
    FETCH cur_dimensions_key INTO var_dimension_key;
    dbms_output.put_line (var_table_name);
    dbms_output.put_line (var_dimension_key);


    END LOOP;
    CLOSE cur_dimension_key;
END LOOP;
CLOSE cur_all_dim;
END;

Solution

  • Static cursors can only access static objects. In other words, static cursors work only if all tables and columns are known at compile time.

    If you need to access a table whose name will only be known during execution, you'll have to use dynamic SQL. For instance, you could use a REF CURSOR in your case:

    DECLARE
       var_table_name    VARCHAR2(30);
       var_dimension_key VARCHAR2(30);
       cur_dimension_key SYS_REFCURSOR;
    BEGIN
       FOR cur_all_dim IN (SELECT table_name
                             FROM dba_tables
                            WHERE dba_tables.tablespace_name = 'USERS'
                              AND dba_tables.owner = 'DWH_CORE'
                              AND UPPER(dba_tables.table_name) LIKE ('%DIM%%')
                              AND UPPER(dba_tables.table_name) NOT LIKE ('%TEMP%')
                              AND UPPER(dba_tables.table_name) NOT LIKE ('%DEBUG%')
                              AND UPPER(dba_tables.table_name) NOT LIKE ('%LOG%')) 
       LOOP      
          OPEN cur_dimension_key 
           FOR 'SELECT dimention_key 
                  FROM ' || cur_all_dim.table_name;
          LOOP
             FETCH cur_dimensions_key INTO var_dimension_key;
             EXIT WHEN cur_dimensions_key%NOTFOUND;
             dbms_output.put_line(cur_all_dim.table_name);
             dbms_output.put_line(var_dimension_key);      
          END LOOP;
          CLOSE cur_dimension_key;
       END LOOP;
    END;