Skip to Main Content
  • Questions
  • Unable to complete finish_redef_table on reference partitioned table

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question.

Asked: May 02, 2019 - 12:49 pm UTC

Last updated: October 07, 2019 - 12:45 am UTC

Version: 12c release1

Viewed 1000+ times

You Asked

Hi ,

Could you please have a look at below reference partition scenario Rowcount of order_items is 25 millions:
I need to change the partition technique of child table i.r. order_items to DAILY-RANGE INTERVAL partition.
Table dont have primary key so i am using cons_use_rowid to redfine.
however i annot able to finish redefintion becasue of below error
------------------------
ORA-02448: constraint does not exist
ORA-06512: at "SYS.DBMS_REDEFINITION", line 105
ORA-06512: at "SYS.DBMS_REDEFINITION", line 3520
ORA-06512: at line 51
02448. 00000 -  "constraint does not exist"
*Cause:    The named constraint does not exist
*Action:   Stop trying to do something with a nonexistant constraint

------------------------

Could you please assist here and if there is any alternative to do this activity please help.

-- sample table and data
drop table order_items_tmp purge;
drop table order_items purge;
drop table orders purge;

CREATE TABLE orders (
  order_id    NUMBER PRIMARY KEY,
  order_date  DATE NOT NULL,
  customer_id NUMBER NOT NULL,
  shipper_id  NUMBER)
PARTITION BY RANGE (order_date) (
  PARTITION y1 VALUES LESS THAN (TO_DATE('01-JAN-2006', 'DD-MON-YYYY')),
  PARTITION y2 VALUES LESS THAN (TO_DATE('01-JAN-2007', 'DD-MON-YYYY')),
  PARTITION y3 VALUES LESS THAN (TO_DATE('01-JAN-2008', 'DD-MON-YYYY')));

CREATE TABLE order_items (
  order_id    NUMBER NOT NULL,
  order_date  date,
  price       NUMBER,
  quantity    NUMBER,
  CONSTRAINT order_items_fk FOREIGN KEY (order_id) REFERENCES orders (order_id))
PARTITION BY REFERENCE (order_items_fk);

insert into orders select level, TO_DATE('01-JAN-2007', 'DD-MON-YYYY'), level, level from dual connect by level <=100;
insert into order_items select order_id, TO_DATE('01-JAN-2020', 'DD-MON-YYYY'), order_id, order_id from orders;
update order_items set order_date = order_date+rownum; -- update for daily dates
commit;


-- Start Redefinition
WHENEVER SQLERROR EXIT SQL.SQLCODE


exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'STORAGE', false);
exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'TABLESPACE', false);
exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'SEGMENT_ATTRIBUTES', false);
exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'CONSTRAINTS', false);
exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'REF_CONSTRAINTS', false);
exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'PARTITIONING', false);
exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'CONSTRAINTS_AS_ALTER', false);
exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'SQLTERMINATOR', false);
exec dbms_metadata.set_transform_param (dbms_metadata.session_transform,'PRETTY', true);

SET SERVEROUTPUT ON SIZE UNLIMITED;

DECLARE
  l_tab_sql      varchar2(32767);
  l_part_sql     varchar2(32767) := q'[PARTITION BY RANGE (order_date) INTERVAL (NUMTODSINTERVAL(1,'DAY')) (PARTITION p_default values less than (TO_DATE('01-JAN-1990', 'DD-MON-YYYY')))]';
  l_errors  NUMBER;
  l_schema_owner varchar2(30) := USER;
  l_orig_table   varchar2(30) := 'ORDER_ITEMS';
  l_int_table    varchar2(30) := 'ORDER_ITEMS_TMP';
BEGIN
  l_tab_sql := dbms_metadata.get_ddl('TABLE',l_orig_table,l_schema_owner);
  l_tab_sql := regexp_replace(l_tab_sql,'(\s+)(CONSTRAINT "?.?")(\w+)?"','\1'||'CONSTRAINT "'||'\3_BKP'||'"',1,1,'im');
  l_tab_sql := replace(l_tab_sql,l_orig_table,l_int_table);
  l_tab_sql := l_tab_sql||l_part_sql;
  
  DBMS_OUTPUT.put_line('Create Interm table => ' || l_tab_sql);
  
  EXECUTE IMMEDIATE l_tab_sql;
  DBMS_OUTPUT.put_line('Interm table created..');
  
  -- drop constraint from int table before starting redefinition..
  begin
    for r in (select table_name, constraint_name from user_constraints where table_name = l_int_table)
    loop
       execute immediate 'alter table '|| r.table_name||' drop constraint '|| r.constraint_name;
    DBMS_OUTPUT.put_line('Constraint ' ||r.constraint_name||' dropped..');
    end loop;
  end;  
  
  DBMS_REDEFINITION.can_redef_table(uname => l_schema_owner, tname => l_orig_table, options_flag => dbms_redefinition.cons_use_rowid);
  
  DBMS_REDEFINITION.start_redef_table(uname => l_schema_owner , orig_table => l_orig_table, int_table  => l_int_table, options_flag => dbms_redefinition.cons_use_rowid);
  
  DBMS_REDEFINITION.sync_interim_table(uname => l_schema_owner , orig_table => l_orig_table, int_table  => l_int_table);
  
  DBMS_REDEFINITION.copy_table_dependents(
    uname            => l_schema_owner,
    orig_table       => l_orig_table,
    int_table        => l_int_table,
    copy_indexes     => DBMS_REDEFINITION.cons_orig_params,
    copy_triggers    => TRUE,
    copy_constraints => TRUE,
    copy_privileges  => TRUE,
    ignore_errors    => FALSE,
    num_errors       => l_errors,
    copy_statistics  => FALSE,
    copy_mvlog       => FALSE);
    
  DBMS_OUTPUT.put_line('Errors=' || l_errors);

  DBMS_STATS.gather_table_stats(l_schema_owner, l_int_table, cascade => TRUE);

  DBMS_REDEFINITION.finish_redef_table(uname => l_schema_owner , orig_table => l_orig_table, int_table  => l_int_table);
  EXECUTE IMMEDIATE 'DROP TABLE '||l_int_table||' CASCADE CONSTRAINTS';
  DBMS_OUTPUT.put_line('Interm table dropped..');
  
END;

and Chris said...

I'm not sure why you're getting the constraint does not exist error. When I run this I get:

ORA-23549: table "CHRIS"."ORDER_ITEMS" involved in reference partitioning


Which, as the error implies, means you can't use DBMS_redefinition on a reference-partitioned table!

I believe you're going to have to do this conversion manually.

Rating

  (2 ratings)

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

Comments

12c version

A reader, May 03, 2019 - 3:52 am UTC

Hi Chris,
My database version is:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
"CORE 12.1.0.2.0 Production"
TNS for Linux: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production

Could you please confirm the version where you executed the redefinition.

Chris Saxon
May 03, 2019 - 9:23 am UTC

I don't see why that matters - DBMS_redefinition is still unsupported on reference partitioned tables as of 19c. https://docs.oracle.com/en/database/oracle/oracle-database/19/vldbg/partition-concepts.html#GUID-54D18B18-6838-4115-9389-E1FB0D20A8CA

ORA-02448 while doing online redef on reference-partitioned table

Baseer, October 06, 2019 - 5:34 pm UTC

I believe the "error message" is an Oracle version issue. I encountered an ORA-02448 when I did this 3 years ago and opened an SR for the issue. This would explain why you're getting a different error, Chris, although you're right in that the same issue still exists in versions beyond 12c.

The error message "ORA-02448: constraint does not exist" is thrown incorrectly when dbms_redefinition is attempted on a table which is involved in reference partitioning. This is a misleading error message and has been fixed as part of below bug:

Bug 18258770 ORA-2448 from DBMS_REDEFINITION.finish_redef_table with constraint to reference partitioned table
After patch 18258770 is applied, below error is thrown instead of ORA-02448, which clearly says that this is an unsupported operation:
ORA-23549: table "SCOTT"."TEST" involved in reference partitioning

Hth
Connor McDonald
October 07, 2019 - 12:45 am UTC

nice input

More to Explore

Design

New to good database design? Check out Chris Saxon's full fundamentals class.