Oracle Scratchpad

June 5, 2012

Truncate Partition

Filed under: Infrastructure,Oracle,Partitioning — Jonathan Lewis @ 5:11 pm UTC Jun 5,2012

A recent posting on the OTN database forum (which I didn’t answer correctly on my first attempt) raised the problem of truncating partitions when there are referential integrity constraints in place. Let’s start with a demonstration of the problem:

create table parent (
	id 	number,
	v1	varchar2(10),
	padding	varchar2(100),
	constraint	p_pk primary key(id) using index local
)
partition by range(id) (
	partition p1000 values less than (1000),
	partition p2000 values less than (2000),
	partition p3000 values less than (3000),
	partition p4000 values less than (4000),
	partition p5000 values less than (5000)
)
;

create table child (
	id_p		number,
	seq_c		number,
	v1		varchar2(10),
	padding		varchar2(100),
	constraint	c_fk_p foreign key (id_p) references parent,
	constraint	c_pk primary key (id_p, seq_c) using index local
)
partition by range(id_p) (
	partition p1000 values less than (1000),
	partition p2000 values less than (2000),
	partition p3000 values less than (3000),
	partition p4000 values less than (4000),
	partition p5000 values less than (5000)
)
;

insert into parent
select
	rownum - 1,
	rpad(rownum - 1,10),
	rpad('x',100)
from
	all_objects
where
	rownum <= 4000
;

insert into child
select
	id,
	val,
	v1,
	padding
from
	parent,
	(
		select 1 val from dual
		union all
		select 2 val from dual
		union all
		select 3 val from dual
		union all
		select 4 val from dual
	)
;

-- gather some stats on the two tables.

alter table child  truncate partition p4000;
alter table parent truncate partition p4000;

The problem is that you can’t truncate the parent partition because Oracle thinks there may be related data in the child partition – despite the fact that the internal code could be written to see that the partition’s data segment was “new”. The output from the two truncate commands is as follows:

-- the call for the child works

Table truncated.

alter table parent truncate partition p4000
            *
ERROR at line 1:
ORA-02266: unique/primary keys in table referenced by enabled foreign keys

You can’t truncate the parent partition unless you disable the foreign key constraint – and it might take quite a long time to re-enable it since we usually only worry about partitioning for large objects.

There is a slightly surprising workaround that might be good enough. If you set the foreign key constraint to novalidate, rather than disable, you can tell Oracle to exchange partitions without checking the validity of the foreign key constraint. So:

create table parent_ex (
	id 	number,
	v1	varchar2(10),
	padding	varchar2(100),
	constraint	px_pk primary key(id)
)
;

create table child_ex (
	id_p		number,
	seq_c		number,
	v1		varchar2(10),
	padding		varchar2(100),
	constraint	cx_fk_px foreign key (id_p) references parent_ex,
	constraint	cx_pk primary key (id_p, seq_c)
)
;

alter table child modify constraint c_fk_p
		rely
		enable
		novalidate 
;

alter table child_ex modify constraint cx_fk_px
		rely
		enable
		novalidate 
;

prompt	============================================================
prompt	We can now exchange the child and parent partitions we want.
prompt	============================================================

alter table child exchange partition p3000 with table child_ex
	including indexes
	without validation
;

alter table parent exchange partition p3000 with table parent_ex
	including indexes
	without validation
;

Having done the two exchanges, we have two empty partitions in the partitioned table and we can truncate the resulting parent_ex and child_ex tables. If we wanted we could also modify the referential integrity constraint back to validate mode – although this would take some time, of course, and we might just decide that it wasn’t necessary because (we believe) all the old data would be correct, and we may only be worried about making sure that new data will be checked.

The downside to this method is that we need to keep (or recreate) a pair of tables in the right tablespace so that we can do the exchange when we need to; but that doesn’t seem to be a terrible price to pay for the ability to “truncate” a single partition without disabling referential integrity constraints.

6 Comments »

  1. In this example the child table could be PARTITION BY REFERENCE(c_fk_p) and then TRUNCATE PARTITION in the parent will be allowed when the corresponding partition in the child is empty.

    In general, PARTITION BY REFERENCE is useful if you have tables connected by a referential constraint and you want to equi-partition the child and parent tables. Partition maintenance operations such as ADD, DROP, SPLIT and MERGE PARTITION will cascade implicitly to the child when performed on the parent. Since the rdbms is enforcing equi-partitioning, the enabled ref constraint does not block operations such as TRUNCATE and EXCHANGE PARTITION when the relevant partition of the other table is empty.

    Comment by George Eadon — June 5, 2012 @ 5:48 pm UTC Jun 5,2012 | Reply

    • George,

      Thanks for highlighting that possibility. The OP was talking about 10g so the option made available through 11g completely slipped my mind.

      Comment by Jonathan Lewis — June 7, 2012 @ 5:47 pm UTC Jun 7,2012 | Reply

  2. Reblogged this on lava kafle kathmandu nepal.

    Comment by lkafle — June 6, 2012 @ 2:47 am UTC Jun 6,2012 | Reply

  3. Jonathan

    You’ve blogged about such a smilar case several years ago

    http://jonathanlewis.wordpress.com/2006/12/10/drop-parent-partition/

    Best regards

    Comment by Houri Mohamed — June 6, 2012 @ 1:37 pm UTC Jun 6,2012 | Reply

    • Mohamed,

      Thanks for that – I really ought to read my own work from time to time ;)

      Interestingly one of the notes I wrote on that blog item claimed that the mechanism described by George Eadon doesn’t work with one particular pattern. However I can’t find the test case to justify the claim, and the quick test I ran based on the description didn’t repeat the problem in 11.1.0.7 or 11.2.0.3, so either there was a limitation in the earliest version that has been addressed, or I was wrong.

      Comment by Jonathan Lewis — June 7, 2012 @ 6:04 pm UTC Jun 7,2012 | Reply

  4. Nice Article,
    I had also written an Article about Disabling and Enabling Constraints, What precautions to be taken while performing these Operations etc.. in http://www.way2db.in/oracle-constraints.html

    Comment by kshashikanth seo (@kshashikanthseo) — June 19, 2012 @ 3:47 am UTC Jun 19,2012 | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 1,393 other followers