Skip to Main Content
  • Questions
  • Changed dropping behavior after assign another index to a primary key

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Norman.

Asked: November 06, 2023 - 1:17 pm UTC

Last updated: November 06, 2023 - 2:47 pm UTC

Version: 19.21.0.0.0

Viewed 1000+ times

You Asked

Hi Tom,

my question is about constraints in combination with indexes.
I have a big amount of tables in multiple environments with primary keys and corresponding indexes like this:

create table Articles
(
  company_id          number,
  article_id          varchar2(30),
  article_description varchar2(500)
);

alter table Articles
  add constraint Articles_PK primary key (COMPANY_ID, ARTICLE_ID) using index;


They have a good primary key, but a less good ordered index for querying. The queries contain article_id and company_id.
Instead of creating new indexes with a better order, i want to change the existing one´s, in order not to unnecessarily increase the number of unuesed indexes.

All environments are running 24/7 and need their uniqueness on the tables.

So i´ve readed the following article of Chris from July:
https://blogs.oracle.com/sql/post/how-to-modify-constraints-in-oracle-database

After this and some other research, i´ve decided to change them the following way:

create unique index Articles_IDX_TMP on Articles (ARTICLE_ID, COMPANY_ID);
alter table Articles modify constraint Articles_PK using index Articles_IDX_TMP;
alter index Articles_IDX_TMP rename to Articles_PK;


This keeps the uniqueness, keeps the order ot the primary key (which is important for other reasons),
doesn´t drop any foreign key constraints which use the primary key, drops the original index and replaces the new ordered index for the old one.

Good till now.

After this, i noticed following difference in dropping a primary key constraint.

When i dropped an primary key constraint before, the corresponding index was dropped automatically.
I executed the following command to drop the constraint:
alter table Articles drop constraint Articles_PK cascade;

and the database fired two commands autmatically:
drop index Articles_PK;
alter table Articles drop constraint Articles_PK cascade;


I´ve seen this after logging all ddl with a trigger on schema level (after ddl on database).

After my above three changes to replace the index of a primary key constraint,
the command:
alter table Articles drop constraint Articles_PK cascade;

isn´t dropping the index (index: Articles_PK) automatically any more.


My question to you is:
Is there any command to alter the index after this he will be automatically dropped with the drop primary key constraint togehter like before?
How can i reorder the index (not primary key) and achieve the same behavior when dropping the primary key, the index will be dropped automatically with it?
Or is there a better way to change them i haven´t found?

Thanks for your help, and a stress-free week.

and Chris said...

I wasn't aware of the MODIFY CONSTRAINT ... USING INDEX ... clause, thanks for sharing!

When you change the primary key to use this new index, you're hitting this:

When you drop a primary key constraint:
* If the primary key was created using an existing index, then the index is not dropped.
* If the primary key was created using a system-generated index, then the index is dropped.


https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/constraint.html#GUID-1055EA97-BA6F-4764-A15F-1024FD5B6DFE

If you want to drop a primary key and ensure the associated index (however it was created) is also removed, use the DROP INDEX clause:

create table articles
(
  company_id          number,
  article_id          varchar2(30),
  article_description varchar2(500)
);

alter table articles
  add constraint articles_pk primary key (company_id, article_id) using index;
  
create unique index articles_idx_tmp on articles (article_id, company_id);

select index_name, constraint_index
from   user_indexes
where  table_name = 'ARTICLES';
/*
INDEX_NAME          CONSTRAINT_INDEX    
ARTICLES_PK         YES                 
ARTICLES_IDX_TMP    NO                  
*/

alter table articles modify constraint articles_pk using index articles_idx_tmp;

select index_name, constraint_index
from   user_indexes
where  table_name = 'ARTICLES';
/*
INDEX_NAME          CONSTRAINT_INDEX    
ARTICLES_IDX_TMP    NO                  
*/

alter index articles_idx_tmp rename to articles_pk;

select index_name, constraint_index
from   user_indexes
where  table_name = 'ARTICLES';
/*
INDEX_NAME     CONSTRAINT_INDEX    
ARTICLES_PK    NO   
*/

alter table articles 
  drop constraint articles_pk
  cascade drop index;

select index_name, constraint_index
from   user_indexes
where  table_name = 'ARTICLES';

--no rows selected


(the CONSTRAINT_INDEX column was added to *_indexes in 19c)

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

More to Explore

Design

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