Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, HARI PRASAD.

Asked: September 10, 2018 - 1:07 pm UTC

Last updated: September 11, 2018 - 9:47 am UTC

Version: 12C

Viewed 10K+ times! This question is

You Asked

Hi Tom,

We are converting oracle tables as partition tables.To do this we are using ORACLE Exchange Partition.
Database version 12C.

Steps we are following.
1.Original table --existing table
    create table tab1(col1 integer,
                      col2 varchar2(100));

2.Currently no date field, So adding a date column and populating using Default SYSDATE
  alter table tab1 add col3 date default sysdate;

 select col#,segcol#,name from sys.col$ where obj#=(select object_id from dba_objects where object_name='TAB1')
1 1 COL1
2 2 COL2
0 3 SYS_NC00003$
3 4 COL3


3.Creating interim table as similar to original table.

create table tab2
partition by range(col3)
 interval(numtodsinterval(1,'DAY')) 
                      (
                              partition PART_01 values less than (TO_DATE('01/09/2018', 'DD/MM/YYYY'))) ENABLE ROW MOVEMENT 
             as select * from tab1 where 1= 2;


4.Using exchange partition to link data from original table.
ALTER TABLE  tab2
EXCHANGE PARTITION PART_01  WITH TABLE  tab1 WITHOUT VALIDATION ;


This is failing with below error
ORA-14097: column type or size mismatch in ALTER TABLE EXCHANGE PARTITION

And when i look columns in user_tab_columns it is matching.But when i look at sys.col$, it is showing a different row with SYS_NC00003$.

This approach working fine in 11G, only getting issue in 12C.
Could you please advise how to get over this.

Thank You.

and Chris said...

First up, there's no need to query sys.col$. Use *_tab_cols!

Anyway, the problem is due to the fast column default add for nullable columns in 12c. This creates the invisible SYS_* column. There are several other features which could lead to system-generated hidden columns. Setting a column unused being a key culprit.

So what to do?

Well this is addressed in bug 17741995. If you install patch 17741995 (included in 12.1.0.2), you can get around this by setting the event 14529:

create table tab1(
  col1 integer,
  col2 varchar2(100)
);

alter table tab1 add col3 date default sysdate;

select column_name, hidden_column
from   user_tab_cols
where  table_name = 'TAB1';

COLUMN_NAME    HIDDEN_COLUMN   
COL3           NO              
SYS_NC00003$   YES             
COL2           NO              
COL1           NO 

Alter session set events '14529 trace name context forever, level 512';

create table tab2
partition by range(col3)
interval(numtodsinterval(1,'DAY'))  (
  partition PART_01 values less than (to_date('01/09/2018', 'DD/MM/YYYY'))
) enable row movement 
as 
  select * from tab1 where 1 = 2;

alter session set events '14529 trace name context off';

alter table tab2
exchange partition part_01 with table tab1 without validation ;

Table TAB2 altered.


See MOS note 2240439.1.

If you're on 12.2, there is another possibility: create the table with the "for exchange with" parameter. Then alter the new table to be partitioned:

drop table tab2 cascade constraints purge;

create table tab2 for exchange with table tab1;

alter table tab2 modify partition by range(col3)
interval(numtodsinterval(1,'DAY'))  (
  partition PART_01 values less than (to_date('01/09/2018', 'DD/MM/YYYY'))
);

alter table tab2
exchange partition part_01 with table tab1 without validation ;

Table TAB2 altered.

Rating

  (2 ratings)

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

Comments

A reader, September 10, 2018 - 4:28 pm UTC

Hi,

Thank you for quick response.
Can we alter session and set below session level setting to false and turn it TRUE after adding column with default value.
alter session set "_add_col_optim_enabled" = false;

Can you please advise what is this parameter and any disadvantages using this parameter?


Thank You.
Chris Saxon
September 11, 2018 - 9:46 am UTC

You should avoid using underscore parameters. Setting event 14529 is the process documented in note 2240439.1.

So use this way. Unless adding the column without a default (as shown in the review below) works for you. In which case do that.

two step

Racer I., September 11, 2018 - 6:47 am UTC

Hi,

I wouldn't use underscore parameters unless necessary. In this case I would rather add the column without default.
Then update it with SYSDATE. Then modify it to have a default.

create table tab1(
col1 integer,
col2 varchar2(100)
);

insert into tab1 values (1, '1');

commit;

alter table tab1 add col3 date;

update tab1 set col3 = SYSDATE;

commit;

alter table tab1 modify col3 date DEFAULT SYSDATE;

create table tab2
partition by range(col3)
interval(numtodsinterval(1,'DAY')) (
partition PART_01 values less than (to_date('01/09/2018', 'DD/MM/YYYY'))
) enable row movement
as
select * from tab1 where 1 = 2;

alter table tab2
exchange partition part_01 with table tab1 without validation ;

regards,
Chris Saxon
September 11, 2018 - 9:47 am UTC

Yes - assuming they don't need the fast column add optimization. If the table's large, that update will take a while...

More to Explore

Administration

Need more information on Administration? Check out the Administrators guide for the Oracle Database