If you drop a unique or primary key constraint the index that supports it may be dropped at the same time – but this doesn’t always happen. Someone asked me recently if it was possible to tell whether or not an index would be dropped without having to find out the hard way by dropping the constraint. The answer is yes – after all, Oracle has to make a decision somehow, so if we can find out how it makes the decision we can predict the decision.
So here’s my best theory so far – along with the observations that led to it. First, run a trace while dropping a primary key constraint and see if this gives you any clues; on an instance running 10gR2 I noticed the following statement appearing in the trace file immediately after the delete from cdef$ (constraint definitions).
select o.owner#, i.property, o.name from obj$ o, ind$ i where i.obj# = o.obj# and o.obj#=:1 ;
Given this clue, the obvious next step is to look in sql.bsq (or dcore.bsq if you’re running 11g) to see what it says about column ind$.property, and we find the following comment:
/* The index was created by a constraint : 0x1000 */
This looks promising, so let’s try a few experiments to see what happens in a few cases of creating indexes and constraints – here’s a starting sample:
create table t1 (n1 number); alter table t1 add constraint t1_pk primary key (n1); create table t1 (n1 number); create unique index t1_pk on t1(n1); alter table t1 add constraint t1_pk primary key (n1);
In the first case (which generated the index automatically) ind$.property held the value 4097; in the second case, where I created the index explicitly, it held the value 1. (For the less mathematically inclined, 0x1000 = decimal 4096). So it would appear that if we want to know if an index would be dropped as the constraint was dropped, we need only check to see if bitand(ind$.property,4096) = 4096. If the predicate evaluates to true the index will be dropped. (But see comment 3 and the subsequent reply below: the test should almost certainly be bitand(ind$.property,4097) = 4097 )
The exact SQL for the check is left as an exercise to the reader – you will probably want to join ind$ to obj$ to user$.
Footnote: this particular bit of the property column doesn’t seem to be exposed in any of the data dictionary views; but if anyone knows of any other way to see it then I’d be interested to hear about it, especially if you don’t have to have access to the sys schema to see it.
Update Oct 2016
Here’s a little bit of SQL I hacked together while I was checking the behaviour of modifying a primary key to “move” it to a different index. It has to be run by SYS, and it references a schema and set of indexes by name (so it’s far from generic) and reports the two critical bits. If both are non-zero then it’s an index that will be dropped if it’s protecting a primary key or unique constraint and you drop or move the constraint:
column object_name format a32 select obj.object_name, bitand(ind.property,1) unique_if_1, bitand(ind.property,4096) sysgen_if_4096 from sys.ind$ ind, ( select object_id, object_name from dba_objects where object_type = 'INDEX' and owner = 'TEST_USER' and object_name in ('T1_I1','T1_PK') ) obj where ind.obj# = obj.object_id ;
Don’t forget to check the possible performance implications of running this query on a database with a very large data dictionary.
Jonathan,
many people (used to) take it for granted that an index gets dropped when its corresponding constraint is disabled or dropped.
The fact is that it used to be like this up until 9iR2, although it was considered a bug (#1240495 on MOS). As soon as this “bug” got fixed in 10g, lots of systems relying on that old behaviour (e.g. for disabling a PK for a load) started to fail.
Interesting to see how you traced those details down.
Kind regards,
Uwe
Comment by Uwe M. Küchler — April 19, 2012 @ 5:17 pm BST Apr 19,2012 |
You can use keep/drop option:
Comment by Valentin Nikotin — April 19, 2012 @ 5:41 pm BST Apr 19,2012 |
Hi Jonathan,
the following testcase let’s me think that your conclusion might not be fully right.
BR,
Martin
Comment by Martin S. — April 19, 2012 @ 7:28 pm BST Apr 19,2012 |
Martin,
Nicely done.
Your second test is one that I did before posting – except I specified uniqueness in the ‘create index’ bit and the index then disappeared with the constraint. You haven’t specified uniqueness (bit 0 – value 1).
So perhaps the requirement is that bitand(property,4097) = 4097 – i.e. automatic and unique.
Comment by Jonathan Lewis — April 19, 2012 @ 7:51 pm BST Apr 19,2012 |
An “Ahaa !” moment when I read this.
Thanks.
Comment by Hemant K Chitale — April 20, 2012 @ 12:28 am BST Apr 20,2012 |
Hi!
Seems this property can be checked through dbms_metadata.
Code is based on example from “Expert Indexing in Oracle Database 11g”:
Comment by Andrew — April 20, 2012 @ 12:52 pm BST Apr 20,2012 |
nice idea, Andrew !
however, if you change
alter table testtab2 modify (a primary key);
into
alter table testtab2 add constraint te_pk primary key (a);
the index is still SYSTEM_GENERATED, but the first block with “dbms_metadata.set_filter(l_myhandle, ‘SYSTEM_GENERATED’, false);” delivers ( falsely ?)
CREATE UNIQUE INDEX “SOKRATES”.”TE_PK” ON “SOKRATES”.”TESTTAB2″ (“A”)
….
( looks like a bug to me, my version is 11.2.0.2.0 )
However, in both cases
bitand(ind$.property,4097)
gives 4097 to me.
Comment by Matthias Rogel — April 20, 2012 @ 2:09 pm BST Apr 20,2012 |
[…] This does not appear to be exposed in any DBA_ view of which I am aware, so I have had to rely upon this post from Jonathan Lewis to help me deciper the information. You need to see if certain bits are set in the column […]
Pingback by Primarys Keys and their supporting indexes | Neil Chandler's DBA Blog — January 29, 2016 @ 7:02 am GMT Jan 29,2016 |
[…] original index when you “move” the primary key – I had overlooked the fact that the way Oracle treats an index can vary with the way in which the index was […]
Pingback by Modify PK | Oracle Scratchpad — November 30, 2018 @ 8:02 am GMT Nov 30,2018 |
[…] couple of other posts on my blog that might also be relevant to the OP, one is about the effect of dropping a primary key constraint the other about the cost of adding a primary key to a […]
Pingback by Quiz Night | Oracle Scratchpad — July 12, 2021 @ 10:24 am BST Jul 12,2021 |