0

I have a code which accepts a table name as parameter and creates subpartitions on that table name for the partitions. My table is partitioned on list of source system codes and range subpartitoned on monthly basis.

Question: If suppose I have variable list of tables and I want to create subpartitions for all then I need to modify this procedure every time to pass varying list of tables. Can I use PLSQL VARRAY or nested table to hold my list of tables, and pass this VARRAY or nested table as a parameter to the below procedure and create subpartitions for all the table names the VARRAY or nested table is holding?

Your help is much appreciated. Many thanks!

Code:

CREATE OR REPLACE PROCEDURE execute_subpartition ( table_name IN varchar2)

IS
 tbl_nm varchar2(30) := table_name;
 sqlstr VARCHAR2(1000);

  CURSOR TabSubPartition IS
  SELECT TABLE_NAME, PARTITION_NAME
  FROM USER_TAB_PARTITIONS
  WHERE TABLE_NAME = tbl_nm
  ORDER BY PARTITION_NAME;
BEGIN
     FOR aSubPart IN TabSubPartition LOOP
       IF TRUNC(LAST_DAY(SYSDATE)) = TRUNC(SYSDATE)
        sqlstr := 'ALTER TABLE TUCEL001.' || aSubPart.TABLE_NAME || ' MODIFY PARTITION ' || 
     aSubPart.PARTITION_NAME ||' ADD SUBPARTITION '  || aSubPart.PARTITION_NAME || '_' || 
     TO_CHAR(TRUNC(LAST_DAY(SYSDATE) + 1), 'MON_YYYY') ||' VALUES LESS THAN (TIMESTAMP ''' || 
     TRIM(to_char(add_months((TRUNC(LAST_DAY(SYSDATE))+1), 1), 'SYYYY-MM-DD HH24:MI:SS', 
     'NLS_CALENDAR=GREGORIAN')) || ''')'; 
     dbms_output.put_line(sqlstr);
     EXECUTE IMMEDIATE sqlstr;
  
    ELSE
          dbms_output.put_line('the condition did not match');
    END IF;
  END LOOP;
Exception
   WHEN OTHERS
   THEN
 dbms_output.put_line('encountered an error, because the sub-partitions which are being created 
  already exists');
END;
Littlefoot
  • 131,892
  • 15
  • 35
  • 57
Sneha
  • 45
  • 12

1 Answers1

2

My 11g doesn't have partitioning enabled so I can't demonstrate it.

But, see if this example (of creating some tables) helps. You don't have to declare your own type - sys.odcivarchar2list should do. Read it using the table function and use its column_value in your dynamic SQL.

Procedure:

SQL> create or replace procedure p_test (par_tables in sys.odcivarchar2list) as
  2    l_str varchar2(200);
  3  begin
  4    for cur_r in (select column_value as table_name
  5                  from table(par_tables)
  6                 )
  7    loop
  8      dbms_output.put_line('table name = ' || cur_r.table_name);
  9      l_str := 'create table ' || dbms_assert.qualified_sql_name(cur_r.table_name) ||
 10               '  (id     number,' ||
 11               '   name   varchar2(20))';
 12      execute immediate(l_str);
 13    end loop;
 14  end;
 15  /

Procedure created.

Testing:

SQL> exec p_test(sys.odcivarchar2list('tab_a', 'tab_b'));

PL/SQL procedure successfully completed.

SQL> desc tab_a;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER
 NAME                                               VARCHAR2(20)

SQL> desc tab_b;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER
 NAME                                               VARCHAR2(20)

SQL>
Littlefoot
  • 131,892
  • 15
  • 35
  • 57
  • I am not able to understand how to use this above example as a solution for my query. :( – Sneha Jul 27 '20 at 09:54
  • In my procedure above I want to pass a list of table names as parameter, which is again processed in the where clause of a select statement inside procedure to get certain records. Further I need to screen throught two column values for all the records given and use those values to create sub partitions. – Sneha Jul 27 '20 at 09:56
  • Exactly as I did; you'd write your own dynamic SQL that does the *partitioning* part of the job. I can't, my database doesn't support partitioning. Apart from that, should be no problem. – Littlefoot Jul 27 '20 at 09:57
  • I'm sorry, but I don't understand what is your problem. I clearly showed how to pass list of tables and how to use it in a WHERE clause. Do you not see that? Perhaps you don't *like* it, but that's a different problem. – Littlefoot Jul 27 '20 at 10:02
  • Many thanks for your above example, I was able to utilise the similar functionality and get the outcome required. In addition to above I used pl/sql nested cursor FOR loop in stored procedure. – Sneha Jul 28 '20 at 07:28
  • OK, I'm glad if you made it work. Thank you for letting us know. – Littlefoot Jul 28 '20 at 07:31
  • Hi, Can you also guide me how to use VARRAY type forthe parameter passed in my stored procedure? Because I actually have to run this procedure using Control-M database job. And When I try to run from Control-M it says this above Oracle pre-defined table type as UNDEFINED. Further investigation says this issue is because may be JDBC driver which connects Control-M to database doesnot support this TYPE. And it can support VARRAY itseems. – Sneha Jul 30 '20 at 07:19
  • Try to create your own type, then. Unfortunately, I don't know anything about "Control-M" so I can't tell what might be wrong. From Oracle point of view, this *works* (as demonstrated). – Littlefoot Jul 31 '20 at 07:43