Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question.

Asked: August 21, 2002 - 4:54 pm UTC

Last updated: October 03, 2011 - 9:39 am UTC

Version: 8.1.7.1.0

Viewed 10K+ times! This question is

You Asked

We have a table that have redundant SYS constraints and we are not sure how it got there. What usually caused this to happen?

Sample output:

SYS_C0010002 AIISPRODUCT_ID
SYS_C0010011 AIISPRODUCT_ID
SYS_C0010873 AIISPRODUCT_ID
SYS_C0010882 AIISPRODUCT_ID
SYS_C0012324 AIISPRODUCT_ID
SYS_C0012333 AIISPRODUCT_ID
SYS_C0012444 AIISPRODUCT_ID
SYS_C0012453 AIISPRODUCT_ID
SYS_C0012693 AIISPRODUCT_ID
SYS_C0012702 AIISPRODUCT_ID
SYS_C0012711 AIISPRODUCT_ID
SYS_C006110 AIISPRODUCT_ID
SYS_C0010007 CUSTTYPE_ID
SYS_C0010016 CUSTTYPE_ID
SYS_C0010878 CUSTTYPE_ID
SYS_C0010887 CUSTTYPE_ID
SYS_C0012329 CUSTTYPE_ID
SYS_C0012338 CUSTTYPE_ID
SYS_C0012449 CUSTTYPE_ID
SYS_C0012458 CUSTTYPE_ID
SYS_C0012698 CUSTTYPE_ID
SYS_C0012707 CUSTTYPE_ID
SYS_C0012716 CUSTTYPE_ID
SYS_C006115 CUSTTYPE_ID
SYS_C0010005 INSETUPFLAG
SYS_C0010014 INSETUPFLAG
SYS_C0010876 INSETUPFLAG
SYS_C0010885 INSETUPFLAG
SYS_C0012327 INSETUPFLAG
SYS_C0012336 INSETUPFLAG
SYS_C0012447 INSETUPFLAG
SYS_C0012456 INSETUPFLAG
SYS_C0012696 INSETUPFLAG
SYS_C0012705 INSETUPFLAG
SYS_C0012714 INSETUPFLAG
SYS_C006113 INSETUPFLAG
SYS_C0013006 LASTMODBY
SYS_C0013005 LASTMODDT
SYS_C0010004 LISTING_ID
SYS_C0010013 LISTING_ID
SYS_C0010875 LISTING_ID
SYS_C0010884 LISTING_ID
SYS_C0012326 LISTING_ID
SYS_C0012335 LISTING_ID
SYS_C0012446 LISTING_ID
SYS_C0012455 LISTING_ID
SYS_C0012695 LISTING_ID
SYS_C0012704 LISTING_ID
SYS_C0012713 LISTING_ID
SYS_C006112 LISTING_ID
SYS_C0010009 LISTINGTYPENAME_ID
SYS_C0010018 LISTINGTYPENAME_ID
SYS_C0010880 LISTINGTYPENAME_ID
SYS_C0010889 LISTINGTYPENAME_ID
SYS_C0012331 LISTINGTYPENAME_ID
SYS_C0012340 LISTINGTYPENAME_ID
SYS_C0012451 LISTINGTYPENAME_ID
SYS_C0012460 LISTINGTYPENAME_ID
SYS_C0012700 LISTINGTYPENAME_ID
SYS_C0012709 LISTINGTYPENAME_ID
SYS_C0012718 LISTINGTYPENAME_ID
SYS_C006117 LISTINGTYPENAME_ID
SYS_C0010003 MAINLISTING_ID
SYS_C0010012 MAINLISTING_ID
SYS_C0010874 MAINLISTING_ID
SYS_C0010883 MAINLISTING_ID
SYS_C0012325 MAINLISTING_ID
SYS_C0012334 MAINLISTING_ID
SYS_C0012445 MAINLISTING_ID
SYS_C0012454 MAINLISTING_ID
SYS_C0012694 MAINLISTING_ID
SYS_C0012703 MAINLISTING_ID
SYS_C0012712 MAINLISTING_ID
SYS_C006111 MAINLISTING_ID
SYS_C0013002 NAMEBUSFLAG
SYS_C0013003 NAMEGOVTFLAG
SYS_C0013004 NAMERESFLAG
SYS_C0010010 OUTPUTFLAG
SYS_C0010019 OUTPUTFLAG
SYS_C0010881 OUTPUTFLAG
SYS_C0010890 OUTPUTFLAG
SYS_C0012332 OUTPUTFLAG
SYS_C0012341 OUTPUTFLAG
SYS_C0012452 OUTPUTFLAG
SYS_C0012461 OUTPUTFLAG
SYS_C0012701 OUTPUTFLAG
SYS_C0012710 OUTPUTFLAG
SYS_C0012719 OUTPUTFLAG
SYS_C006118 OUTPUTFLAG
SYS_C0010008 SERVICETYPE_ID
SYS_C0010017 SERVICETYPE_ID
SYS_C0010879 SERVICETYPE_ID
SYS_C0010888 SERVICETYPE_ID
SYS_C0012330 SERVICETYPE_ID
SYS_C0012339 SERVICETYPE_ID
SYS_C0012450 SERVICETYPE_ID
SYS_C0012459 SERVICETYPE_ID
SYS_C0012699 SERVICETYPE_ID
SYS_C0012708 SERVICETYPE_ID
SYS_C0012717 SERVICETYPE_ID
SYS_C006116 SERVICETYPE_ID
SYS_C0010006 STATUS
SYS_C0010015 STATUS
SYS_C0010877 STATUS
SYS_C0010886 STATUS
SYS_C0012328 STATUS
SYS_C0012337 STATUS
SYS_C0012448 STATUS
SYS_C0012457 STATUS
SYS_C0012697 STATUS
SYS_C0012706 STATUS
SYS_C0012715 STATUS
SYS_C006114 STATUS



I have an additional question not related to this one. Is it safe to run root.sh after you already a working database? Does it need a relink afterwards.

Thanks again in advance.


and Tom said...

I'm going to assume you use EXP/IMP alot and you clearly rely on "un-named constraints" -- constraints with system generated names.

Here is a short extract from my book "Expert one on one", from the chapter on IMP/EXP, that details exactly what has happened here:

<quote>
Named versus Default Named Constraints

Here is another issue with regards to system-generated named constraints and IMP/EXP. I could have called this section Where Did All of These Constraints Come From? since the prior section was called Where Did My Indexes Go? Here we start with a table T:

tkyte@TKYTE816> create table t
2 ( x int check ( x > 5 ),
3 y int constraint my_rule check ( y > 10 ),
4 z int not null ,
5 a int unique,
6 b int references t,
7 c int primary key
8 );
Table created.

tkyte@TKYTE816> select constraint_name name, constraint_type type, search_condition
2 from user_constraints where table_name = 'T';

NAME T SEARCH_CONDITION
------------------------------ - -------------------------
SYS_C002674 C "Z" IS NOT NULL
SYS_C002675 C x > 5
MY_RULE C y > 10
SYS_C002677 P
SYS_C002678 U
SYS_C002679 R

6 rows selected.

It has lots of constraints on it – six all together. I'll export it, drop the table and import it again:

tkyte@TKYTE816> host exp userid=tkyte/tkyte owner=tkyte

tkyte@tkyte816> drop table T;
Table dropped.

tkyte@TKYTE816> host imp userid=tkyte/tkyte full=y ignore=y rows=n

tkyte@TKYTE816> select constraint_name name, constraint_type type, search_condition
2 from user_constraints where table_name = 'T';

NAME T SEARCH_CONDITION
------------------------------ - -------------------------
SYS_C002680 C "Z" IS NOT NULL
SYS_C002681 C x > 5
MY_RULE C y > 10
SYS_C002683 P
SYS_C002684 U
SYS_C002685 R

6 rows selected.

Looks normal so far. Lets say however, that we rerun the import for whatever reason (it failed part way through for example). What we'll then discover is:

tkyte@TKYTE816> host imp userid=tkyte/tkyte full=y ignore=y

Import: Release 8.1.6.0.0 - Production on Tue Mar 20 15:42:26 2001

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production

Export file created by EXPORT:V08.01.06 via conventional path
import done in WE8ISO8859P1 character set and WE8ISO8859P1 NCHAR character set
. importing TKYTE's objects into TKYTE
. . importing table "T" 0 rows imported
IMP-00017: following statement failed with ORACLE error 2264:
"ALTER TABLE "T" ADD CONSTRAINT "MY_RULE" CHECK ( y > 10 ) ENABLE NOVALIDAT"
"E"
IMP-00003: ORACLE error 2264 encountered
ORA-02264: name already used by an existing constraint
IMP-00017: following statement failed with ORACLE error 2261:
"ALTER TABLE "T" ADD UNIQUE ("A") USING INDEX PCTFREE 10 INITRANS 2 MAXTRAN"
"S 255 STORAGE(INITIAL 524288) TABLESPACE "DATA" ENABLE"
IMP-00003: ORACLE error 2261 encountered
ORA-02261: such unique or primary key already exists in the table
About to enable constraints...
Import terminated successfully with warnings.

tkyte@TKYTE816> select constraint_name name, constraint_type type, search_condition
2 from user_constraints where table_name = 'T';

NAME T SEARCH_CONDITION
------------------------------ - -------------------------
SYS_C002680 C "Z" IS NOT NULL
SYS_C002681 C x > 5
MY_RULE C y > 10
SYS_C002683 P
SYS_C002684 U
SYS_C002685 R
SYS_C002686 C x > 5

7 rows selected.

We have an extra constraint. In fact, every time we run this, we'll have an extra constraint added. My named constraint however generates a warning on screen – you cannot have the same named constraint twice. The un-named constraint for “x > 5” on the other hand – gets created again. This is because the database just generated a new name for it.

I've seen cases where people have been using EXP on one database, truncating the data on another, and using IMP to put the data back in. Over time they had accumulated hundreds of check constraints on many columns. Performance was starting to go downhill and they wanted to know why. The above is the reason why. Every time they copied the data, they added yet another bunch of check constraints, all doing the same work. See what the effect of just a one hundred will do:

tkyte@TKYTE816> create table t
2 ( x int check ( x > 5 )
3 )
4 /
Table created.

tkyte@TKYTE816> declare
2 l_start number default dbms_utility.get_time;
3 begin
4 for i in 1 .. 1000
5 loop
6 insert into t values ( 10 );
7 end loop;
8 dbms_output.put_line
9 ( round((dbms_utility.get_time-l_start)/100,2) || ' seconds' );
10 end;
11 /
.08 seconds

PL/SQL procedure successfully completed.

tkyte@TKYTE816> begin
2 for i in 1 .. 100
3 loop
4 execute immediate
5 'ALTER TABLE "TKYTE"."T" ADD CHECK ( x > 5 ) ENABLE ';
6 end loop;
7 end;
8 /
PL/SQL procedure successfully completed.

tkyte@TKYTE816> declare
2 l_start number default dbms_utility.get_time;
3 begin
4 for i in 1 .. 1000
5 loop
6 insert into t values ( 10 );
7 end loop;
8 dbms_output.put_line
9 ( round((dbms_utility.get_time-l_start)/100,2) || ' seconds' );
10 end;
11 /
.17 seconds

PL/SQL procedure successfully completed.

Yet another good reason to name your constraints!


Rating

  (14 ratings)

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

Comments

Tina, August 22, 2002 - 7:54 am UTC

Thanks for the explanation. It makes sense now. I checked the constraint type for all of them and all are indeed check constraints. If we do need to redo an import, do we avoid this by dropping the table, re-creating it and then importing the data back. What is meant by 'name your constraints'?

Tom Kyte
August 22, 2002 - 9:11 am UTC


You can avoid this by dropping the table and letting IMPORT create it.

By "name your constraints" I mean:

tkyte@TKYTE816> create table t
2 ( x int check ( x > 5 ),
3 y int constraint my_rule check ( y > 10 ),

X has an unnamed constraint
Y has a named constraint

The nice thing is if you violate the constraint on Y, you can a nice friendly message "my_rule violated". If you violate the constraint on X, you get "SYS_C02432432 violated" which tells you next to nothing.

Very interesting

A reader, August 22, 2002 - 2:41 pm UTC


Everyday!

A reader, August 22, 2002 - 7:38 pm UTC

So far I have learned something new (and beneficial) everyday from this site
Thanks Tom

Duplicate Sys Constraints

Raj, June 10, 2005 - 3:32 am UTC

Hi tom,

SORRY TO ASK 4 QUESTIONS IN THE SAME MAIL ...

Can u please suggest

1. How to remove all the duplicate sys constraints

From the follow up:-

tkyte@TKYTE816> select constraint_name name, constraint_type type,
search_condition from user_constraints where table_name = 'T';

NAME T SEARCH_CONDITION
------------------------------ - -------------------------
SYS_C002681 C x > 5
SYS_C002686 C x > 5

2. Methods to replace the system generated constraint by user defined constraint name.
For ex:
SYS_C002681 - translated into - TABLE_NAME_SEQ
(SEQ - SEQUENCE running from 1 to N.)

3. Is there any package/method that gives me
1. Create table script
2. Index,Primary key,Foreign Key,comment,
synonums scripts
3. Scripts for
Ex: Table A and B
Col1 and col2 in Table A
col3 and col4 in table B

B has Foreign Key on table A. If am going to drop TABLE A and recreate, i have to recreate the Foreign key of Table B also.

Scripts for generating the foreign key on the depending tables too.

**no tablespaces, no schema names in those scripts**

4.Suggest some good way for
- Creating a copy of a table in another schema
i. only structure, No data required.
ii. All scripts of Question #3.

Thanks
Raj

Tom Kyte
June 10, 2005 - 8:39 am UTC

1) you can drop constraints.
2) you can rename them.
3) dbms_metadata
4) see #3



error in oracle

champ, December 09, 2005 - 8:26 pm UTC

ORA-02264: name already used by an existing constraint

I got this error when I going to create some tables. How to avoid this?

Tom Kyte
December 10, 2005 - 5:17 am UTC

use another name for your constraint??? just like you cannot have two tables with the same name..............

How to Identify the Duplicate sys constraints

NM Sanjai Kumaar, December 29, 2005 - 10:49 pm UTC

Hi Tom,
Thanks for the earlier suggessions given.

Could you please explain on how to find out the duplicate sys constraints on the tables. In my case there are about 7000+ table in the schema. I see that there are several duplicate Check constraints in each table. Is there any query or package to identify those constraints tablewise

Thanks in Advance

Tom Kyte
December 30, 2005 - 9:12 am UTC

there are many ways, but I'll show the "lazy - no code" way.

ops$tkyte@ORA10GR2> create table t
  2  ( x int check ( x > 5 ),
  3    y int constraint my_rule check ( y > 10 ),
  4    z int not null ,
  5    a int unique,
  6    b int references t,
  7    c int primary key
  8  );

Table created.

ops$tkyte@ORA10GR2>
ops$tkyte@ORA10GR2> !exp userid=/ tables=t

Export: Release 10.2.0.1.0 - Production on Fri Dec 30 09:07:42 2005

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
Export done in US7ASCII character set and AL16UTF16 NCHAR character set
server uses WE8ISO8859P1 character set (possible charset conversion)

About to export specified tables via Conventional Path ...
. . exporting table                              T          0 rows exported
Export terminated successfully without warnings.

ops$tkyte@ORA10GR2> !imp userid=/ tables=t ignore=y

Import: Release 10.2.0.1.0 - Production on Fri Dec 30 09:07:42 2005

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

Export file created by EXPORT:V10.02.01 via conventional path
import done in US7ASCII character set and AL16UTF16 NCHAR character set
import server uses WE8ISO8859P1 character set (possible charset conversion)
. importing OPS$TKYTE's objects into OPS$TKYTE
. importing OPS$TKYTE's objects into OPS$TKYTE
. . importing table                            "T"          0 rows imported
IMP-00017: following statement failed with ORACLE error 2264:
 "ALTER TABLE "T" ADD CONSTRAINT "MY_RULE" CHECK ( y > 10 ) ENABLE NOVALIDATE"
IMP-00003: ORACLE error 2264 encountered
ORA-02264: name already used by an existing constraint
About to enable constraints...
Import terminated successfully with warnings.

ops$tkyte@ORA10GR2>
ops$tkyte@ORA10GR2> select constraint_name, constraint_type, search_condition from user_constraints;

CONSTRAINT_NAME C SEARCH_CONDITION
--------------- - --------------------
SYS_C006043     C  x > 5
SYS_C006042     R
MY_RULE         C  y > 10
SYS_C006038     C  x > 5
SYS_C006037     C "Z" IS NOT NULL
SYS_C006040     P
SYS_C006041     U

7 rows selected.

ops$tkyte@ORA10GR2>
ops$tkyte@ORA10GR2> create table t2
  2  as
  3  select table_name, constraint_name cn, to_lob(search_condition) sc
  4    from user_constraints
  5   where constraint_type = 'C'
  6  /

Table created.

ops$tkyte@ORA10GR2>
ops$tkyte@ORA10GR2> select table_name, cn, dbms_lob.substr(sc,4000,1) search_condition,
  2         row_number() over (partition by table_name, dbms_lob.substr(sc,4000,1) order by cn) rn
  3    from t2
  4  /

TABLE_NA CN              SEARCH_CONDITION             RN
-------- --------------- -------------------- ----------
T        SYS_C006038      x > 5                        1
T        SYS_C006043      x > 5                        2
T        MY_RULE          y > 10                       1
T        SYS_C006037     "Z" IS NOT NULL               1

ops$tkyte@ORA10GR2> select 'alter table ' || table_name || ' drop constraint ' || cn || ';'
  2    from (
  3  select table_name, cn, dbms_lob.substr(sc,4000,1) search_condition,
  4         row_number() over (partition by table_name, dbms_lob.substr(sc,4000,1) order by cn) rn
  5    from t2
  6         )
  7   where rn > 1
  8  /

'ALTERTABLE'||TABLE_NAME||'DROPCONSTRAINT'||CN||';'
-------------------------------------------------------------------------------
alter table T drop constraint SYS_C006043;

 

Will it cause any damage ?

A reader, December 30, 2005 - 2:15 pm UTC

If just leave the duplicate sys_* constraints there?

Tom Kyte
December 31, 2005 - 10:50 am UTC

read original reply - damage is "performance"

Duplicate SYS constraints

Nina, November 16, 2006 - 10:15 am UTC

Very useful explanation and scripts to remove

Excessive check constraints and performance

MK, May 16, 2008 - 5:40 am UTC

Hi Tom,

Questions in regards to Check Constraints. I am currently reviewing a database schema and have come across tables that use Check constrains very excessively, every single column in this fat table has check constraints listed on it.





SQL> select constraint_name, search_condition, status, validated from user_constraints where table_name = 'ARTIST' and constraint_type = 'C';


<b>CONSTRAINT_NAME                SEARCH_CONDITION                                                                 STATUS   VALIDATED

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

CKC_TRACK_SET_ID_ARTIST        TRACK_SET_ID is null or (TRACK_SET_ID >= 0)                                      ENABLED  VALIDATED

CKC_PRIMARY_IMAGE_ID_ARTIST    PRIMARY_IMAGE_ID is null or (PRIMARY_IMAGE_ID >= 0)                              ENABLED  VALIDATED

CKC_IMAGE_SET_ID_ARTIST        IMAGE_SET_ID is null or (IMAGE_SET_ID >= 0)                                      ENABLED  VALIDATED

CKC_STORY_SET_ID_ARTIST        STORY_SET_ID is null or (STORY_SET_ID >= 0)                                      ENABLED  VALIDATED

CKC_CELEBRITY_PLAYLIS_ARTIST   CELEBRITY_PLAYLIST_ID is null or (CELEBRITY_PLAYLIST_ID >= 0)                    ENABLED  VALIDATED

CKC_ARTIST_INFLUENCER_ARTIST   ARTIST_INFLUENCERS_SET_ID is null or (ARTIST_INFLUENCERS_SET_ID >= 0)            ENABLED  VALIDATED

CKC_ARTIST_FOLLOWERS__ARTIST   ARTIST_FOLLOWERS_SET_ID is null or (ARTIST_FOLLOWERS_SET_ID >= 0)                ENABLED  VALIDATED

CKC_ARTIST_CONTEMPORA_ARTIST   ARTIST_CONTEMPORARIES_SET_ID is null or (ARTIST_CONTEMPORARIES_SET_ID >= 0)      ENABLED  VALIDATED

CKC_BIOGRAPHY_STORY_I_ARTIST   BIOGRAPHY_STORY_ID is null or (BIOGRAPHY_STORY_ID >= 0)                          ENABLED  VALIDATED

CKC_EDITOR_NOTE_ID_ARTIST      EDITOR_NOTE_ID is null or (EDITOR_NOTE_ID >= 0)                                  ENABLED  VALIDATED

CKC_BORN_IN_COUNTRY_ARTIST     BORN_IN_COUNTRY is null or (BORN_IN_COUNTRY = upper(BORN_IN_COUNTRY))            ENABLED  VALIDATED

CKC_FIRST_RELEASE_COU_ARTIST   FIRST_RELEASE_COUNTRY is null or (FIRST_RELEASE_COUNTRY = upper(FIRST_RELEASE_CO ENABLED  VALIDATED

CKC_ENABLED_ARTIST             ENABLED in (0,1)                                                                 ENABLED  VALIDATED

CKC_ADULT_CONTENT_ARTIST       ADULT_CONTENT in (0,1)                                                           ENABLED  VALIDATED

CKC_ONLY_SELL_COMPLET_ARTIST   ONLY_SELL_COMPLETE_RELEASE in (0,1)                                              ENABLED  VALIDATED

CKC_KIND_ARTIST                KIND is null or (KIND in ('BAND','ORCHESTRA','COMPOSER','SONGWRITER','CONDUCTOR' ENABLED  VALIDATED

CKC_GUID_ARTIST                GUID = lower(GUID) and length(GUID) = 32                                         ENABLED  VALIDATED

SYS_C004040                    "ID" IS NOT NULL                                                                 ENABLED  VALIDATED

SYS_C004041                    "PRIMARY_GENRE_ID" IS NOT NULL                                                   ENABLED  VALIDATED

SYS_C004042                    "ENABLED" IS NOT NULL                                                            ENABLED  VALIDATED

 

CONSTRAINT_NAME                SEARCH_CONDITION                                                                 STATUS   VALIDATED

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

SYS_C004043                    "ADULT_CONTENT" IS NOT NULL                                                      ENABLED  VALIDATED

SYS_C004044                    "ONLY_SELL_COMPLETE_RELEASE" IS NOT NULL                                         ENABLED  VALIDATED

SYS_C004045                    "GUID" IS NOT NULL                                                               ENABLED  VALIDATED

SYS_C004046                    "SHORT_NAME" IS NOT NULL                                                         ENABLED  VALIDATED

SYS_C004047                    "NAME" IS NOT NULL                                                               ENABLED  VALIDATED

SYS_C004048                    "DATA_CLASSIFICATION" IS NOT NULL                                                ENABLED  VALIDATED

SYS_C004049                    "CREATED" IS NOT NULL                                                            ENABLED  VALIDATED

SYS_C004050                    "INSERTED" IS NOT NULL                                                           ENABLED  VALIDATED

SYS_C004051                    "MODIFIED" IS NOT NULL                                                           ENABLED  VALIDATED

CKC_ID_ARTIST                  ID >= 0                                                                          ENABLED  VALIDATED

CKC_PRIMARY_GENRE_ID_ARTIST    PRIMARY_GENRE_ID >= 0                                                            ENABLED  VALIDATED

CKC_PRIMARY_STORY_ID_ARTIST    PRIMARY_STORY_ID is null or (PRIMARY_STORY_ID >= 0)                              ENABLED  VALIDATED

 

32 rows selected</b>





a. How does this affect performance of the DML? What are the negative impacts of doing such excessive checks? The combination of named and unnamed constraints is due to using a 3rd party tool to generate the DDL for table creation.



b. How can I combine them into meaningful checks or maybe even get rid of some checks? I have advised to use Lookup tables instead of hard-coding values in the check constraints.



c. Is it advisable to have the constraints in "enable not validated" mode so the checks only take place on INSERTs? Would I notice an improvement in performance?



Index Related Qn.



d. Can you please direct me to the script you written to weed out duplicate indexes? I had run it a while back but cannot find it anymore.



e. Can I get rid of a FK Index if it is the leading column in an already existing multi-column index?



Thanks,

MK
(Not sure if the formatting is working?)

Tom Kyte
May 19, 2008 - 3:00 pm UTC

a) who cares, it is much faster than if you tried to do it yourself and it is the only correct way to do it - they MUST be enforced or they do not exist.

This is not excessive.
This is good.

b) and a look up table would be what? Oh, yet another check (foreign key).

For something like this:

... KIND is null or (KIND in
('BAND','ORCHESTRA','COMPOSER','SONGWRITER','CONDUCTOR' ...

if it is a small list, we need not bother with a lookup table, unless the lookup table would be useful somewhere else (like in a pick list).

c) ummm, what would be the point here - why would you want to do that in this case???

d) don't remember having one, but it is pretty straight forward:

ops$tkyte%ORA11GR1> /*
ops$tkyte%ORA11GR1>
ops$tkyte%ORA11GR1> drop table t;
ops$tkyte%ORA11GR1>
ops$tkyte%ORA11GR1> create table t ( a int, b int, c int, d int );
ops$tkyte%ORA11GR1> create index t_idx1 on t(a,b,c,d);
ops$tkyte%ORA11GR1> create index t_idx2 on t(a,b);
ops$tkyte%ORA11GR1> */
ops$tkyte%ORA11GR1>
ops$tkyte%ORA11GR1> with index_data
  2  as
  3  (
  4  select index_name, table_name, column_name, column_position, descend, count(*) over (partition by index_name) col_cnt
  5    from user_ind_columns
  6   where table_name not like 'BIN$%'
  7  )
  8  select table_name, index_name, might_be_covered_by
  9    from (
 10  select a.table_name,
 11         a.index_name,
 12             b.index_name might_be_covered_by,
 13             a.column_position,
 14             a.col_cnt,
 15             count(*) over (partition by a.index_name, b.index_name) col_cnt2,
 16             a.column_name acol, b.column_name bcol
 17    from index_data a, index_data b
 18   where a.table_name = b.table_name
 19     and a.index_name <> b.index_name
 20     and a.column_name = b.column_name
 21     and a.column_position = b.column_position
 22     and a.descend = b.descend
 23     and a.col_cnt <= b.col_cnt
 24         )
 25   where col_cnt = col_cnt2
 26     and column_position = 1
 27  /

TABLE_NAME                     INDEX_NAME                     MIGHT_BE_COVERED_BY
------------------------------ ------------------------------ ------------------------------
T                              T_IDX2                         T_IDX1

ops$tkyte%ORA11GR1>




e) if your fk is (a,b,c) and you have any index that starts with (a,b,c,.....) the foreign key is indexed enough already

Re-Excessive check constraints and performance

MK, May 21, 2008 - 12:12 pm UTC

(a) Point taken. Only thought that it might be easier to merge a few constraint conditions.

(b) The lookup is to have a reference table that is used by web applications as a drop down and can grow with time. Instead of modifying the table's DDL I much rather prefer that there be a separate lookup table that can be inserted into and updated every time a change occurs. These values are volatile and can grow with time.

(c) ok.. was wondering if the check constraint would enforce it's check when a new row came in rather than checking all existing rows in the table? Shouldn't that perform better in theory?

(d) I am pretty sure you had this query to detect redundant and duplicate indexes on tables. It would detect every index that was already being covered by an existing index.
Something similar I found out there
http://www.dba-oracle.com/t_detecting_duplicate_indexes.htm
but thanks for your new script regardless.

(e) Maybe I should ask it with a better example ...
I have a unique index like IDX_A (A, B, C) and FK indexes like IDX_FK_A (A) and IDX_FK_B (B). My question was whether it is ok to drop IDX_FK_A as it is the leading column in IDX_A anyway? Would this cause problems with SQL joins which used IDX_FK_A?

Thanks in advance.
Tom Kyte
May 21, 2008 - 2:50 pm UTC

(b) absolutely then, it should have been a lookup table from day one given that requirement.

(c) you want them to check all existing data if you are adding them after the fact.

(d) well, if I did I didn't keep it because it is rather easy to just do it - it doesn't take that monster query :)


(d) Well, I said:

if your fk is (a,b,c) and you have any index that starts with (a,b,c,.....) the foreign key is indexed enough already

You have a foreign key (A)
You have an index on (A,B,C)

foreign key (A) is covered by that index on (A,B,C)
foreign key (B) is NOT since B is not on the leading edge of (A,B,C)


Now, that said, the index on (A,B,C) will be likely larger (two times or more maybe) than the index on (A) by itself. So, the index on (A) by itself could be more efficient to use than (A,B,C) - especially if the index on (A) was used in a fast full or full index scan. Also, the index on (A) could have a really good clustering factor and the index on (A,B,C) might not so the index on (A) might be used for larger range scans than an index on (A,B,C) would

So, the answer is: maybe yes, maybe no, maybe both yes and no. In other words:

It depends

which is why I used the term " MIGHT_BE_COVERED_BY " above - you need to use your knowledge of the data and your knowledge of how the indexes might be used in order to answer your question "would it cause problems"

Thanks

MK, May 28, 2008 - 12:16 pm UTC

Thanks Tom. That made it all clear to me now. Have to post a materialized view and rewrite query related problem now! :)

Name me one good reason why duplicate constraints are not a "BUG"

A reader, August 22, 2011 - 1:23 am UTC

Duplicate constraints has always been a bug.

Why doesn't Oracle know what a duplicate check condition is?

I mean, we spend our money on Oracle because it is, well, Oracle. Allowing 500 of the same constraint is a defect, I'm sorry. I can think of no good reason why Oracle should allow one duplicate, much less unlimited duplicates.

Besides that, system named constraints have always been kludgy. Explicitly naming NOT NULL constraints is busy work. Should not be required. Give us decent system-generated names. I for one would like to see Oracle "reboot" the architecture and fix a few of the issues that have become part of the landscape.
Tom Kyte
August 30, 2011 - 2:09 pm UTC

hah, define what a "decent system generated name" would be. Remember - no collisions, 30 characters.


duplicate constraints are not a bug - you might think it is an undesirable side effect - but definitely not a bug.

We do what you ask us to do. The constraint name is unique - that is all.


do you see a need to name not null constraints? if so, why? They are not 'duplicated'

only unnamed check constraints are - and naming them would not be busy work.


but - in the end - I am not the arbitrare of what is or is not a bug - support is. And you, as a paying customer, do have the ability to put in enhancement requests. That is the only way to get something like this changed ultimately.

System generated names...

A reader, October 02, 2011 - 9:37 am UTC

Hi Tom,
I completely agree with your responses. If anything, I wish Oracle would do away with system generated names for constraints all together. Explicitly naming objects in the database should be required. When you need to be sure that schemas or databases are in sync it is very difficult to do diffs when you have system generated names. Also, what does it take; maybe an additional 5 seconds to type the syntax for explicitly naming the constraint.
Tom Kyte
October 03, 2011 - 9:39 am UTC

agreed...

but others would complain "hey, it takes me 5 seconds more - it is too complex"... ;)

Importing Check constraints.

Nitesh, November 12, 2013 - 9:45 am UTC

I got much idea on check constraints while importing the tables . But i got small doubt on the same , please try to clear me .. While importing it use to show as "Enabling Constraints" since i am doing import of tables newly along with the constraints , triggers and indexes. Then why check constraints alone remains in disabled mode where as Primary Key and Unique Keys gets enabled .. Can u please clear this alone.

More to Explore

VLDB

If you are new to partitioning, check out Connor McDonald's introduction series here.

VLDB

Documentation set on VLDB and Partitioning.