top of page
  • Writer's pictureBalaaji Dhananjayan

Convert Non Partitioned table into Partitioned

It happens to be DBAs sometime end up converting non partitioned table into partitioned table based on new use cases or requirements whether to split the table based on Range for future maintenance operations or to Hash it for better performance, and what not.


However it is DBAs responsibility to seamlessly convert a normal table into a partitioned one (or vice versa) without affecting the application or requesting for a downtime to perform the same.


Let's see how to easily get this done..


--Create a Sample table:

CREATE TABLE invoices
(invoice_no    NUMBER NOT NULL,
 invoice_date  DATE   NOT NULL,
 comments      VARCHAR2(500)
 );
SQL> insert into INVOICES values ('12345', systimestamp,'This is a test');

1 row created.

SQL> commit;

Commit complete.

--Verify if the table can be redefined

begin
dbms_redefinition.can_redef_table
 (uname=>'SCHEMA_NAME',
 tname=>'INVOICES',
 options_flag=>DBMS_REDEFINITION.CONS_USE_ROWID);
end;
/

PL/SQL procedure successfully completed

--(This means the table is eligible for Redefinition)

Follow below steps or format and put this into a script as you want..

--Step 1: 
SET SERVEROUTPUT ON
SET LINESIZE 100
SET VERIFY OFF
SET FEEDBACK ON
SET TERMOUT OFF
SET TIMING ON
spool invoices_refer.log

-- Step2: Create interim table 

CREATE TABLE invoices_int
(invoice_no    NUMBER NOT NULL,
 invoice_date  DATE   NOT NULL,
 comments      VARCHAR2(500)
 )
PARTITION BY RANGE ("INVOICE_DATE") INTERVAL (NUMTODSINTERVAL(1,'DAY')) 
(PARTITION "P0"  VALUES LESS THAN (TIMESTAMP' 1900-01-01 00:00:00')) ;

--Step3: Start Redefinition

-- Use this only if your table is big in size and wanted to increase the parallelism

ALTER SESSION FORCE PARALLEL DML PARALLEL 4;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 4;

BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE
 (uname=>'SCHEMA_NAME',
 orig_table=>'INVOICES',
 int_table=>'INVOICES_INT',
 options_flag=>DBMS_REDEFINITION.CONS_USE_ROWID);
end;
/

Sync table is required to load the delta after the redefinition was started

--Step4: SYNC Interim table

BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE
 (uname=>'SCHEMA_NAME',
 orig_table=>'INVOICES',
 int_table=>'INVOICES_INT');
end;
/

Copying Dependents. Kindly read through Oracle documentation as which dependants to copy.

I am intentionally including copy_constraints to generate an error.

--Step5: Copy Dependents

SET SERVEROUTPUT ON
DECLARE
  l_num_errors PLS_INTEGER;
BEGIN
  DBMS_REDEFINITION.copy_table_dependents(
    uname             => 'SCHEMA_NAME',
    orig_table        => 'INVOICES',
    int_table         => 'INVOICES_INT',
    copy_indexes      => DBMS_REDEFINITION.cons_orig_params, -- Non-Default
    copy_triggers     => TRUE,  -- Default
    copy_constraints  => TRUE,  -- Default
    copy_privileges   => TRUE,  -- Default
    ignore_errors     => TRUE, 
    num_errors        => l_num_errors); 
  DBMS_OUTPUT.put_line('l_num_errors=' || l_num_errors);
END;
/

-- Use below script to find errors. You should see one which is intentional.

set lines 200
set long 99999999
col object_type for a10
col object_owner for a20
col base_table_name for a20
select object_type, object_owner, base_table_name, ddl_txt from dba_redefinition_errors;

Just in case if you have to change your mind and cancel the Redefinition process (Only if needed).

exec DBMS_REDEFINITION.ABORT_REDEF_TABLE(uname=>'SCHEMA_NAME', orig_table=>'INVOICES', int_table=>'INVOICES_INT'); -- reference
--Step6: Finish Redefinition

begin
dbms_redefinition.finish_redef_table
 (uname=>'SCHEMA_NAME',
 orig_table=>'INVOICES',
 int_table=>'INVOICES_INT');
end;
/  

Now see if you have successfully converted the table using below query.

select owner, table_name, PARTITIONING_TYPE from dba_part_tables where table_name='INVOICES';

Hope this helps you. Cheers!!


Regards,

Balaaji Dhananjayan

524 views0 comments

Recent Posts

See All
bottom of page