Not very intuitive on RELY/NORELY
Mike, December 18, 2001 - 3:35 pm UTC
I have been reading Oracle doc on the constraint states of RELY/NORELY,
There is no good example to illustrate these. Could give us some examples of these?
December 18, 2001 - 4:31 pm UTC
<quote>
RELY/NORELY
specifies whether an enabled constraint is to be enforced. Specify RELY to enable an existing constraint without enforcement. Specify NORELY to enable and enforce an existing constraint. The default is NORELY.
Unenforced constraints are generally useful only with materialized views and query
rewrite. Depending on the QUERY_REWRITE_INTEGRITY mode (see "ALTER SESSION" on
page 7-83), query rewrite can use constraints that are enabled with or without enforcement to determine join information.
</quote>
RELY is sort of like a "trust me" mode. You can use it in a data warehouse where you have loaded "scrubbed" data. You can have a constraint enabled without being enforced (trust me -- that column is UNIQUE, that foreign key -- its OK, that check constraint -- its accurate). We can use that in query rewrites against materialized views. If you are interested in a larger example showing the query rewrite (takes a bit of setup and walking through) I have a chapter on materialized views in my book that describes the use of this setting and why its relevant.
Confusing
Kulguru, December 18, 2001 - 5:43 pm UTC
Iam confused
the following insert should succeed as, the the constraint is enable to no validate , that is validation should not occur and as such the insert should succeed.
ops$tkyte@ORA817.US.ORACLE.COM> alter table t add constraint check_cons check (
x > 0 ) enable novalidate;
Table altered.
ops$tkyte@ORA817.US.ORACLE.COM> insert into t values (0);
insert into t values (0)
*
ERROR at line 1:
ORA-02290: check constraint (OPS$TKYTE.CHECK_CONS) violated
Kindly clarify
December 18, 2001 - 7:04 pm UTC
novalidate is used to put a constraint on a table with EXISTING data and have it get turned on without checking each row (eg: in a data warehouse where you "scrubbed" the data)
ops$tkyte@ORA817DEV.US.ORACLE.COM> create table t ( x int );
Table created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> insert into t values ( 0 );
1 row created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> alter table t add constraint check_cons check ( x > 0 ) enable novalidate ;
Table altered.
ops$tkyte@ORA817DEV.US.ORACLE.COM> insert into t values ( -1 );
insert into t values ( -1 )
*
ERROR at line 1:
ORA-02290: check constraint (OPS$TKYTE.CHECK_CONS) violated
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from t;
X
----------
0
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM>
What you might be looking for is a DISABLED constraint.
deferrable - but is it deferred or immediate right now...
A reader, December 18, 2001 - 7:41 pm UTC
Having played with this (based on your previous writings), my understanding is that the constraint you want to temporarily violate must be deferrable. To temporarily violate it though, you need to put your session into a state where the constraints are deferred, and then you can manually set them bad to immediate enforcement, or let the commit/rollback restore the state for you once you are done with the temporary violation.
SQL> CREATE TABLE dept
2 (deptno NUMBER NOT NULL PRIMARY KEY ,
3 deptname VARCHAR2(30) NOT NULL );
Table created.
SQL>
SQL> CREATE TABLE emp
2 (empno NUMBER NOT NULL PRIMARY KEY,
3 empname VARCHAR2(20) NOT NULL,
4 deptno NUMBER,
5 CONSTRAINT emp_fk1 foreign key (deptno) references dept(deptno) DEFERRABLE);
Table created.
SQL>
SQL> insert into dept values (10, 'Sales');
1 row created.
SQL> insert into emp values (1, 'Joe', 10);
1 row created.
SQL> commit;
Commit complete.
SQL>
SQL> -- see if we can do it with just deferrable constraints
SQL> begin
2 update dept set deptno = 100 where deptno = 10;
3 update emp set deptno = 100 where deptno = 10;
4 end;
5 /
begin
*
ERROR at line 1:
ORA-02292: integrity constraint (SCOTT.EMP_FK1) violated - child record found
ORA-06512: at line 2
SQL> -- no - we need to set the constraints to deferred in this session first
SQL> -- in pl/sql block because most applications would typically use it this way
SQL> begin
2 Execute immediate 'SET CONSTRAINTS ALL DEFERRED';
3 update dept set deptno = 100 where deptno = 10;
4 update emp set deptno = 100 where deptno = 10;
5 -- set them back on again now that we are done
6 -- else they are reset to default (immediate)
7 -- on commit/rollback
8 Execute immediate 'SET CONSTRAINTS ALL IMMEDIATE';
9 end;
10 /
PL/SQL procedure successfully completed.
SQL> select * from dept;
DEPTNO DEPTNAME
---------- ------------------------------
100 Sales
SQL> select * from emp;
EMPNO EMPNAME DEPTNO
---------- -------------------- ----------
1 Joe 100
SQL>
December 18, 2001 - 8:39 pm UTC
No -- this isn't anything to do with deferrable constraints. Deferrable constraints are those that you can have us check upon commit instead of when the statement executes.
What we have here are constraints that are NOT CHECKED BY ORACLE EVER. They are used with data warehouses where you load the data (and you are 100% sure the data is "clean"). You need the constraints to be in place for query rewrites and other features -- but there is no reason to revalidate that a column is unique or satisfies some check constraint, etc. This lets us turn the constraint ON without verifying the existing data is OK. YOU must be 100% SURE the data is OK or else you will get incorrect results.
I was off the point a bit
A reader, December 19, 2001 - 2:11 pm UTC
Sorry about my misleading posting above. It was more to do with your statement "Constraints may be deferrable meaning they are not checked until commit time".
I discovered that commit and "SET CONSTRAINTS ALL IMMEDIATE" both cause validation at that point and that commit/rollback and "SET CONSTRAINTS ALL IMMEDIATE" end the "SET CONSTRAINTS ALL DEFERRED" session setting. I guess setting the state back to immediate (in a several statement transaction) as soon as the it is no longer required (rather than waiting for the commit) allows errors to be trapped as soon as they occur.
Thanks for your insightful original answer.
Locking ?
Christo Kutrovsky, June 10, 2003 - 11:02 am UTC
I just happen to discover that when validating an enabled constraint does not lock the table for DML, can you confirm this please?
is there any special case where the table is locked (for DML), when the constraint has been enabled but not validated? Does that apply only to Foreign Key (my case)?
And why is this not mentioned in the documention?
June 10, 2003 - 11:32 am UTC
if you just "discovered it".. why would i need to validate it -- but it does appear you have it backwards? if I understand you.
but anyway, if you "alter table T add constraint check_cons check (something...)", and look at v$lock (do it on a big table, so you can)
TY ID1 ID2 LMODE REQUEST
-- ---------- ---------- ---------- ----------
TM 31146 0 4 0
1 row selected.
it takes a TM mode 4 lock out on the table. That is like issuing "lock table in share mode". The concepts guide (chapter 20 on data concurrency and consistency) has a table that shows what locks are compatible with what other locks.
Now, an INSERT is going to get a LMODE=3 on that table (row-X, row exclusive lock). The table in the concepts guide shows that an "S" lock is incompatible with a "RX" lock.
All of the locks are documented in the concepts guide.
I really need "test cases" to demonstrate what it is you are doing. "validating an enabled constraint" -- i don't truly know what you imply by that sentence -- what operation you were really doing.
Follow up.
Christo Kutrovsky, June 10, 2003 - 11:42 am UTC
I don't have a test case, because I would need to create a big table (which actuall takes some time to validate)
alter table X add constraint X_FK foreign key (col) references MASTER_TABLE NOVALIDATE;
then,
alter table X modify constraint X_FK validate;
This is the command that takes time. I maybe did a premature conclusion, but i *think* the table was available for selects and inserts/updates .
Please correct me if I am wrong.
June 10, 2003 - 12:40 pm UTC
correct (it doesn't take that much to create a big enough table, I do it all of the time on my laptop).
The modify constraint validate does not take a table level lock out. It is not changing the structure/definition of the table (as the alter + validate would). It only needs a read consistent view of the table to valid since it knows that all modified data will already conform to the constraint.
Thank You.
Christo Kutrovsky, June 10, 2003 - 1:22 pm UTC
Thank You Tom.
I could not find a confirmation about that in the Oracle documenation. Did I miss it? I am about to submit a documentation bug about this issue.
June 10, 2003 - 1:50 pm UTC
There is no doc bug, we don't list specifically what each and every variation of each and every command takes as far as locks go.
*Many* DDL's take an LMODE=4 for their duration. SELECTS are OK, modifications are not.
Some DDL's take an LMODE=4 for a brief instant either at the end or the beginning (alter index rebuild online for example) and release it.
This alter valid is one that takes the 4 mode lock briefly at the beginning and then releases it. If you modify the table in question and then in another session attempt to validate the constraint, you would observe:
big_table@ORA920> alter table big_table modify constraint big_table_check2 validate;
alter table big_table modify constraint big_table_check2 validate
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified
That the constraint cannot be -- that is one of the DDL's that get it for a brief moment and then release it.
Also, bear in mind that the rules change over time -- they are constantly looking at these things and changing them -- either making them more restrictive (typically in reaction to an identified bug -- if we didn't lock more restrictively, there would be a problem) or less restrictive (like the alter index rebuild ONLINE for example) to make things "easier"
Follow up
Christo Kutrovsky, June 10, 2003 - 2:14 pm UTC
Well, maybe not as a "bug" but as an "adition" to the documentation.
Before posting, I was diging trough asktom and found the following:
</code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:950829834856 <code>
and there is a book that does mention that first enabling novalidate, and then validating doesn't lock your table which is a pretty important "feature". I do consider it important, and I was very amazed that it's not pointed in the documentation because it is an important point, your table is (almost) fully available during this (sometimes) lenghty process...
Especially given the fact the 9i is going towards more "online" tasks this would be a valuable adition.
How to make a constraint "deferrable"?
Kamal Kishore, September 09, 2003 - 9:52 pm UTC
Hi Tom,
I'm trying to make a constraint (that is NOT DEFERRABLE) back to DEFERRABLE but getting the following error. Looked at the documentation for the MODIFY CONSTRAINT clause and it seems to suggest the same syntax that I am using. Is there something that I missed (or did wrong)?
How else to do this?
Thanks,
SQL> alter table emp add constraint fk_emp_deptno foreign key (deptno) references dept(deptno)
2 not deferrable initially immediate ;
Table altered.
SQL>
SQL> alter table emp modify constraint fk_emp_deptno deferrable ;
alter table emp modify constraint fk_emp_deptno deferrable
*
ERROR at line 1:
ORA-00933: SQL command not properly ended
SQL>
September 10, 2003 - 10:36 am UTC
you cannot modiy a constraint to be deferrable (or non deferrable)
you would drop and recreate the constraint. since you know the data is valid, you can do it without actually revalidating the data.
Sorry, forgot to add version...
Kamal Kishore, September 09, 2003 - 9:58 pm UTC
SQL> disconnect
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.3.0 - Production
SQL>
why is deferrable not the default
A reader, September 10, 2003 - 6:06 pm UTC
It would be nice to have deferrable as default when constraints are created, since the change requires recreate constraints. Deferrable merely adds the capability of being made deferred. Why oracle did not make it default?
September 10, 2003 - 8:23 pm UTC
it would change pre-existing behavior.
it would cause primary keys to not have unique indexes created.
it was not the way it always worked in the past.
new features like this are generally something "you choose to use"
No unique indexes?
Just an egg..., September 27, 2003 - 1:39 am UTC
Re: "cause primary keys to not have unique indexes created".
I hope I rightly appreciate the DEFERRABLE index will be created at the time of the first commit, which would make a poor default....also that being unique, this would apply to a constraint based PRIMARY KEY USING INDEX?
And I hope VALIDATE RELY would be a kind of oxymoron, or at least illogical?
But I know I need more info around INITIALLY IMMEDIATE, if you would be so kind....
Thanks in anticipation :-)
September 27, 2003 - 10:40 am UTC
sorry, i'm not really following the train of thought here....
....
I hope I rightly appreciate the DEFERRABLE index will be created at the time of
the first commit,
.....
no, the index will be created -- if it needs to be created at all (might already exist) at the time the constraint is added....
which would make a poor default
....
default what?</code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:10954765239682 <code>
is about initially immediate
Clarification
Tom, September 27, 2003 - 4:12 pm UTC
On "default what?", you said immediately above that DEFERREBLE was not the default for four reasons.
I posited that your second reason "it would cause primary keys to not have unique indexes created.", would make DEFERRABLE a poor default option, and asked if it would apply to a PRIMARY KEY USING INDEX. Now I'm more confused by your follow-on statement: "no, the index will be created -- if it needs to be created at all (might already exist) at the time the constraint is added." - which doesn't reconcile with "it would cause primary keys to not have unique indexes created.".
I hope that's easily clarified.
Also, the difference between NORELY and VALIDATE remains unclear, and on IMMEDIATE, should your statement that DEFERRABLE constraints are "not checked until commit time.", be qualified instead to say INITIALLY DEFERRED DEFERRABLE constraints are not checked until commit time?
Thanks in advance.
September 27, 2003 - 4:22 pm UTC
sorry -- i couldn't pick up that meaning from this:
I hope I rightly appreciate the DEFERRABLE index will be created at the time of
the first commit, which would make a poor default.
"which would make a poor default" seems to be going with "at the time of the first commit"
When you create a (non deferrable) primary key on a table -- if the primary key values are NOT already indexed -- Oracle will create a UNIQUE index on those columns.
When you create a deferrable primary key on a table -- if the primary key values are NOT already indexed -- Oracle will create a non-UNIQUE index on those columns.
When you create a primary key on a table and the columns are already indexed, Oracle will just rely on that index for primary key enforcement.
I said "an index" -- never saying "a unique index" or "a non-unique", just an index will be created if needed.
"a constraint in deferred mode" is not checked until commit time.
Of course of course
Tom, October 04, 2003 - 3:20 am UTC
Thanks also for the related supplemental information.
So non-unique indexes and deferred constraints go together, like this?
1) Create deferred constraint, 2) load bad data, 3) clean data with help from non-unique index, 4) drop constraint, 5) drop index, 6) recreate constraint non-deferred and get a unique index?
October 04, 2003 - 9:50 am UTC
well, i would not be into doing steps 4, 5, 6!
it would be
"create constraint. constraint just HAPPENS to be deferrable. if you want the constraint checking to be deferred, set constraint CNAME deferred. If not, just use it as it is."
and that is it. you just leave it that way
Integrity check towards the materialized view [PK on M View, FK on another table]
Prince, November 15, 2003 - 11:32 am UTC
Respected Tom,
I have a materialized view named my_mview having the primary key column employee_code in a database say Y. Suppose this my_mview is completely refreshed every night and it gets the information of employees from several tables of any other database say Z. In database Y there is a table emp_north having column employee_code. I wanna reference this column to employee_code in my_mview (my_mview_employee_code_pk) in the same database. When I establish this using foreign key constraint emp_north_employee_code_fk. It suppresses the refresh of the materialized view...
SQL> exec dbms_mview.refresh('my_mview');
BEGIN dbms_mview.refresh('my_mview'); END;
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-02266: unique/primary keys in table referenced by enabled foreign keys
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 794
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 851
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 832
ORA-06512: at line 1
How can this type of integrity be enforced on emp_north in Oracle9i?
Regards,
November 15, 2003 - 11:46 am UTC
you would need to do a couple of things
a) create a snapshot group so the refresh is performed with a DELETE + INSERT instead of a TRUNCATE + INSERT. Just create another dummy MV (say a snapshot of dual) and create a refresh group with both MV's in it -- that is what you'll refresh
b) recreate the fkey constraint on the child table to be a DEFERRABLE constraint -- one that is validated at the end of the refresh.
then, it can work -- but bear in mind that DELETE + INSERT is going to perform slightly differently then TRUNCATE + INSERT does now!!!!!
DELETE + INSERT ?
Prince, November 15, 2003 - 12:26 pm UTC
Would you like to please elaborate... How can I create a snapshot group so the refresh is performed with a DELETE + INSERT instead of a TRUNCATE + INSERT.
Regards,
November 16, 2003 - 10:27 am UTC
search for
"snapshot group" dual truncate
on this site
Changing datatype without dropping constraints
Pinaki Bhattacharya, February 13, 2004 - 6:48 am UTC
Hi Tom,
Thanks for all you have done for the Oracle community.
I have two tables...P_TYPE and AC_PROJECT
P_TYPE(table)
p_type_code varchar2(2) Primary Key --column
......
......
AC_TYPE(table)
ac_type_code varchar2(2) Primary Key --column
p_type_code varchar2(2) Foreign Key relation to p_type_code in P_TYPE table.
Now I want to change the datatype of the p_type_code to char(2) in both the tables
P_TYPE and AC_TYPE without dropping the constraint.
Will disabling the constraint allow me to change the datatype of the columns?
Thanks
Pinaki
February 13, 2004 - 10:11 am UTC
you won't be doing that. (char's stink anyhow, you'd be going the wrong direction).
You'll need to drop the constraint in order to do the alter which could rewrite both tables (to pad out the p_type_code).
Maybe your best solution is just:
alter table p add constraint ( check (length(p_type_code) = 2) );
that you can add right now, it'll have the same effect (varchar2 and char use the SAME storage methods, but a char is just blank padded -- if you make sure the field is 2 characters -- you have exactly the same bytes on disk).
Could you please explain??
Gerhard, May 03, 2004 - 8:58 am UTC
Dear Tom,
I am not able to understand the "Rely and Norely" attributes of constraints.Could you please explain in simple words *what they are intended for*?
Please do reply.
May 03, 2004 - 1:55 pm UTC
Constraint States:
RELY NORELY
ENFORCED No No
TRUSTED Yes No
STALE_TOLERATED Yes No
it has to do with query rewrite (materialized views, views) and when the constraint will be "used"
In query_rewrite_integrity = TRUSTED -- if the constraint was put in with "norely" -- it would not be used for rewrite (we would not assume the fkey was really 'there' and in place). for rely -- it would use it (even if Oracle has not validated the "fact")
Subash, May 04, 2004 - 4:45 am UTC
Could you please explain the purpose of
1. Disabled novalidate
2. Disabled validate
constraint states with example.
Thanks
May 04, 2004 - 7:27 am UTC
the novalidate/validate don't really count when the constraint is disabled.
Subash, May 04, 2004 - 12:48 pm UTC
Thanks for Ur prompt reply.
You answered
"the novalidate/validate don't really count when
the constraint is disabled."
But my question is
what is the purpose of Disable Novalidate/validate constraint states.Can you please give me the details of it.
May 04, 2004 - 2:06 pm UTC
ummm? not sure what else to say really. As the line from a famous movie goes "Ignore that man behind the curtain", "Ignore novalidate/validate when disable = true"
plz clarify
A reader, July 23, 2004 - 8:17 am UTC
hi tom,
i'm very consfused with these constraint states,plz check this example once..
SQL> create table gg (no number primary key initially deferred);
Table created.
SQL> desc gg
Name Null? Type
------------------------------- -------- ----
NO NUMBER
SQL> insert into gg values(1);
1 row created.
SQL> insert into gg values(1);
1 row created.
SQL> select * from gg;
NO
-----------
1
1
SQL> insert into gg values(1);
1 row created.
SQL> alter table gg
2 modify primary key enable novalidate;
alter table gg
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-00001: unique constraint (SCOTT.SYS_C0043633) violated
SQL> alter table gg modify primary key enable novalidate;
Table altered.
SQL> insert into gg values(1);
1 row created.
SQL> insert into gg values(1);
1 row created.
SQL> alter table gg modify primary key disable validate;
alter table gg modify primary key disable validate
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-00001: unique constraint (SCOTT.SYS_C0043633) violated
SQL> alter table gg modify primary key disable validate;
Table altered.
SQL> select * from gg;
no rows selected.
SQL> insert into gg values(1);
insert into gg values(1)
*
ERROR at line 1:
ORA-25128: No insert/update/delete on table with constraint (SCOTT.SYS_C0043633) disabled and
validated.
y tom,it has to insert the data atleast once into the table but it not doing y as the table constains no data...
tom i understood from the doc that,
enable novalidate-enables the constraint but the constraint is not checked with the data..this is happening my example above also..
disable validate-disables the constraint but it checks with the data its not happening here at all its not allowing me insert even one row of data...
1. plz explain me
2.tom, is there any way to force the primary key,unique or check constraint on table already contains some duplicate,null values...this can be done to not null constraint by using ENFORCE keyword...
plz forgive me if there is any ignorance and kindly expalin me these concepts
July 23, 2004 - 9:06 am UTC
can you summarize your questions more clearly.
[tkyte@localhost tkyte]$ oerr ora 25128
25128, 00000, "No insert/update/delete on table with constraint (%s.%s) disabled and validated"
// *Cause: Try to insert/update/delete on table with DISABLE VALIDATE constraint.
// *Action: Change the constraint's states.
//
seems to be "fairly obvious"
a primary key cannot contain nulls.
a unique key can.
a unique constraint could be added with enabled novalidate.
constraint states
a reader, July 24, 2004 - 12:07 am UTC
hi tom, sorry if i'm not clear in my first one, i understood the concepts till enable novalidate but i can't understand the disable validate one..plz explain me with my previous example.
2.tom, plz tell me if anyone can force the primary key on the table having duplicate values.can it ignore the previous values and it works from now..u can do it for not null constraint by using the enforce keyword..plz tell me
July 24, 2004 - 11:20 am UTC
see
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:950829834856#21106374932242
it is useful with loading partitioned tables in a DW to avoid having to redo lots of work.
2) yes, it is easy:
ops$tkyte@ORA9IR2> create table t ( x int );
Table created.
ops$tkyte@ORA9IR2> insert into t values ( 1 );
1 row created.
ops$tkyte@ORA9IR2> insert into t values ( 1 );
1 row created.
ops$tkyte@ORA9IR2> alter table t add constraint t_pk primary key(x)
2 deferrable
3 enable novalidate
4 /
Table altered.
ops$tkyte@ORA9IR2> select * from t;
X
----------
1
1
ops$tkyte@ORA9IR2> insert into t values ( 1 );
insert into t values ( 1 )
*
ERROR at line 1:
ORA-00001: unique constraint (OPS$TKYTE.T_PK) violated
user_constraints.deferred
Urs, June 06, 2005 - 4:39 am UTC
Hi Tom,
this is my test case:
Oracle9i Enterprise Edition Release 9.2.0.6.0 - 64bit Production
JServer Release 9.2.0.6.0 - Production
SQL> drop table child;
Table dropped.
SQL> drop table parent;
Table dropped.
SQL> create table parent (x number primary key);
Table created.
SQL> create table child (x number);
Table created.
SQL> alter table child
2 add constraint fk foreign key(x)
3 references parent
4 deferrable initially immediate;
Table altered.
SQL> select constraint_name, deferrable, deferred from user_constraints
2 where constraint_name = 'FK';
CONSTRAINT_NAME DEFERRABLE DEFERRED
------------------------------ -------------- ---------
FK DEFERRABLE IMMEDIATE
SQL> set constraint fk deferred;
Constraint set.
SQL> select constraint_name, deferrable, deferred from user_constraints
2 where constraint_name = 'FK';
CONSTRAINT_NAME DEFERRABLE DEFERRED
------------------------------ -------------- ---------
FK DEFERRABLE IMMEDIATE
Shouldn't DEFERRED now be something other than 'IMMEDIATE', e.g. 'DEFERRED'?
How can I find out if a constraint has been set in deferred state?
Thanks, Urs
June 06, 2005 - 7:27 am UTC
the constraints DEFINITION won't change, just it's current status.
I know of know way to query the current status (you set it, you should sort of know). If you NEED it deferred, there is no harm in deferring it.
Large transactions and deferred constraints
Urs, June 09, 2005 - 9:06 am UTC
Hi Tom,
I am wondering how Oracle keeps track of integrity constraint violations while constraints are deferred.
I can think of two ways:
A) They keep a list of rowids of all changed rows and check the constraints at commit time or „set constraint immediate“ time. This is contrary to what I observe: commit is about as fast as with no constraints deferred.
B) They keep a list of rowids that temporarily violate deferred constraints and check this list after each dml action, adding and removing rowids as appropriate.
If B) is correct or not completey false, I have three questions:
1. Where is the list/table/hash map?
2. Is there a maximum size for the list or a size that you would not recommend to exceed.
3. Can it be configured, eg. initial size, pct_increase...
I am observing that, with deferred constraints and large transactions, updates are becoming significantly slower when v$transaction.used_urec comes near 15.000.000. Maybe the cost for searching the list and resizing it grows quadratically. Splitting large transactions into several small ones makes it MUCH faster. But that’s what you would call a „bad transaction habit“.
Btw., what do these tiny light grey numbers at the bottom
of asktom pages tell us?
Cheers, Urs
June 09, 2005 - 11:06 am UTC
</code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:7913917986287#38212121745266 <code>
for the numbers...
as for the constraints thing -- they would not have to keep a list of all rows modified, just those that "don't make it" -- and at commit time, regardless of the size of this list, just the first row that failed would need be reported. In fact, they could be taking things on and off of this list as modifications are made (so the existence of a thing in the list indicates "failure")
but it really isn't even a question of deferred constraints, what about:
create table t ( x int primary key );
insert into t select rownum from ten_billion_row_table;
commit;
update t set x = x+1;
the constraints are not verified conceptually until the statement is "done" (they cannot be, the first row updated will conflict with an existing row!)
for your udpates, are most of the rows "in violation" during this processing and cleaned up at the end -- or are most of the rows "OK" with few violations?
Large transactions and deferred constraints
A reader, June 09, 2005 - 11:39 am UTC
Tom,
more than 90% of the updated rows are "in violation".
We have a master table with some 100.000 composite keys in it.
The last column of the key is to be expanded from 4 to 5 digits,
following certain(...) rules and changing each and every number.
Then we have some 30 child and "grandchild" tables referencing
these keys. Most, but not all references are enforced by foreign
key constraints.
About 20.000.000 rows per schema.
6 databases, 2 schemas each.
Limited time for the update.
Hopefully this will not happen again in the next ten years ...
Thanks for your help,
Urs
June 09, 2005 - 6:11 pm UTC
probably a case for disable constraint, do your work, enable constraint. I can imagine you'll want to disable indexes and other things as well on primary/foreign keys to do this mass conversion in many cases.
Deferrable indexes and Streams
Thomas Starr, July 14, 2005 - 2:11 am UTC
Is there a best way to convert constraints back to non-deferrable schema wide on an active system?
In this case to optimize Streams parallelism and eliminate the complexity of an unneeded feature.
10g RAC & Streams
July 14, 2005 - 10:28 am UTC
you have to drop and recreate them, that is the only way.
How to see error message on commit failure?
Mathew Butler, July 18, 2005 - 9:49 am UTC
We have a set of deferrable constraints. We have a thrid party product. The third party product is failing with "could not commit". Obviously this app has modified data in such a way that it is inconsistent with our constraints at commit time.
Is there some way to identify the complete error message that the application is hiding? Any other way to investigate this?
Thanks as always.
Why does enabling a constraint prevent queries?
yas, August 03, 2005 - 9:24 am UTC
Tom,
In Oracle9i Performance Tuning Guide and Reference (in the chapter Understanding Indexes and Clusters) it says:
"If you change a constraint from disabled to enabled, then the table must be locked.
No new DML, queries, or DDL can occur, because there is no mechanism to ensure
that operations on the table conform to the constraint during the enable operation."
I set up a test case for this. When i tried to enable a disabled check constraint, i could not query the table from another session when the enable was going on. What may be the reason for this? Why does Oracle prevent queries?
August 03, 2005 - 11:52 am UTC
I'll hypothesize -- the query cannot be optimized because the optimizer can and will take into consideration constraints, and this constraint is not yet fully baked.
Very good stuff.
Orlando Reyes, October 13, 2005 - 9:12 pm UTC
Tom,
When I try to update a table that is the parent of two other tables I get the error:
ORA-02292: integrity constraint (Constraint_FK) violated
child record found.
Problem is I am not updating the primary key of this table, just a file that has nothing to do with the FK constraint.
In metalink they say that this could happen if the field being updated is part of an index where part of the PK is, this is not the case here either. Also, they say that if the PK index is created before the PK constraint is created this could happen.
I deleted the PK constraint and PK index and recreated them again, the problem went away for a few minutes, but after trying two more times to update the table, I got the same error.
I am using 9.2.0.5.0 standard description.
Could you please help me out to understand what is going on here, I never saw this before.
Thanks a lot as usual.
Orlando
October 14, 2005 - 7:25 am UTC
"just a file"??? what do you mean by that.
as always, without an example - it is very hard to comment.
How load
Jay, February 03, 2006 - 6:58 am UTC
Hi, Tom. I want to insert a 4 milion of records in a datawarehouse table. I don't need to validate de primary key, I know that the data is correct. This table have 8 index, and 1 primary key. Is my code correct?
1. truncate dw_table
2. make indexes and constraints unusables
FOR x IN ( SELECT 'alter index ' || index_name ||' unusable ' stmt
FROM all_indexes
where table_name='dw_table')
LOOP
EXECUTE IMMEDIATE x.stmt;
END LOOP;
FOR x IN ( SELECT 'alter table '|| v_NomTabla ||' disable constraint '|| constraint_name||' KEEP INDEX' stmt
FROM all_constraints
where table_name='dw_table'
and constraint_type='P')
LOO
EXECUTE IMMEDIATE x.stmt;
END LOOP;
3. Insert /* APPEND PARALLEL*/ INTO dw_table
SELECT /*+ DRIVING_SITE("tab_prod") */ * FROM "tab_prod"@dblink a
commit;
4. make indexes and constraints usables
same as 2, with this stmt:
Indexes:
'alter index ' || index_name ||' rebuild '
constraint:
'alter table '|| v_NomTabla ||' ENABLE novalidate constraint '|| constraint_name
Is this the fast way to do? thanks
February 03, 2006 - 5:15 pm UTC
are you loading 4million records into an already loaded table? or is the table empty?
Jay
A reader, February 06, 2006 - 2:38 am UTC
The table is empty. I make a truncate before.
February 07, 2006 - 12:33 am UTC
looks fine unless you want to add some parallel to the indexes if it makes sense and perhaps nologging if you have a backup scheduled to take place right after.
but don't over analyze it - it is just 4 million records, not too big.
script
Kulguru, April 29, 2006 - 12:16 am UTC
Tom
I need to load data into a table, and for that purpose disable all the foregin key references on the table. Can you please provide the link to the script.
Thx
April 29, 2006 - 3:06 am UTC
what script?
script
Kulguru, April 29, 2006 - 8:24 pm UTC
I need to disable all foreign key references on a table before data is loaded into that table. I'm trying to put together a script which will spool disable constraint sql statements in a .sql.
Please help.
April 30, 2006 - 4:59 am UTC
all you need to do then is query user_constraints where constraint_type = 'R', I don't have a script for you. Therefore in response to "Can you please provide the link to the script." the answer would be "no" since I don't have one.
A reader, April 30, 2006 - 3:01 pm UTC
Kulguru,
I did search on this site and this is what i found
begin
for x in ( select 'alter table ' || table_name ||
' disable constraint ' || constraint_name stmt
from user_constraints
where constraint_type = 'R' )
loop
dbms_output.put_line( x.stmt );
execute immediate x.stmt;
end loop;
for x in ( select 'truncate table ' || table_name stmt
from user_tables )
loop
dbms_output.put_line( x.stmt );
execute immediate x.stmt;
end loop;
for x in ( select 'alter table ' || table_name ||
' enable constraint ' || constraint_name stmt
from user_constraints
where constraint_type = 'R' AND STATUS='DISABLED' )
loop
dbms_output.put_line( x.stmt);
execute immediate x.stmt;
end loop;
end;
modify as per your requirement.
autocommit *VERSUS* deferred constraints
Duke Ganote, February 05, 2007 - 4:01 pm UTC
SQL*PLUS by default autocommits. Too bad if you're counting on that with deferrable constraints!
SQL*Plus: Release 10.2.0.1.0 - Production on Mon Feb 5 15:48:29 2007
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
SQL> create table t ( t number primary key );
Table created.
SQL> create table u ( u number, constraint u_fk_to_t
2 foreign key ( u ) references t ( t )
3 deferrable initially deferred );
Table created.
SQL> insert into u values ( 99 );
1 row created.
SQL> insert into t values ( 9 );
1 row created.
SQL> exit
log back in again...
SQL> select * from t;
no rows selected
SQL> select * from u;
no rows selected
SQL> insert into u values ( 88 );
1 row created.
SQL> insert into t values ( 8 );
1 row created.
SQL> commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (U_FK_TO_T) violated - parent key not found
... the error on exit/autocommit doesn't get captured in a spool file for the first session, either!
I'm pretty sure that I could see the error thrown in SQL*PLUS before the first session's window closed...
February 05, 2007 - 6:35 pm UTC
sqlplus does NOT autocommit.
by default, sqlplus will commit before an exit, that is NOT autocommit (auto commit is comment after each row)
and sqlplus printed it out, you just didn't see it for whatever reason:
ops$tkyte%ORA10GR2> insert into t values ( 9 );
1 row created.
ops$tkyte%ORA10GR2> exit
ERROR:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (OPS$TKYTE.U_FK_TO_T) violated - parent key
not found
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options (with complications)
[tkyte@localhost ~]$
different states of integrity constraints on version-enabled tables
Sokrates, February 06, 2007 - 3:36 am UTC
Hallo Tom,
is the following a Bug or expected behaviour ?
sokrates > create table temp(i integer, constraint temp_pk primary key(i));
Table created.
sokrates > select constraint_type, status, validated from user_constraints where constraint_name='TEMP_PK';
C STATUS VALIDATED
- -------- -------------
P ENABLED VALIDATED
sokrates > exec dbms_wm.enableversioning(table_name=>'TEMP', validTime=>true, hist=> 'NONE')
PL/SQL procedure successfully completed.
sokrates > select constraint_type, status, validated from user_constraints where constraint_name='TEMP_PK';
C STATUS VALIDATED
- -------- -------------
P DISABLED NOT VALIDATED
I am not able do ENABLE TEMP_PK
Is this behaviour correct ?
(At least it is undocumented)
February 06, 2007 - 11:08 am UTC
when you version enable a table, you don't own the table structure anymore - it (dbms_wm) does. It does the 'right thing' here, it just cannot use your original constraints anymore - your key value will be duplicated.
SQL*PLUS vs autocommit vs EXIT ROLLBACK
Duke Ganote, February 07, 2007 - 12:13 pm UTC
Thx
Sokrates, February 08, 2007 - 4:17 am UTC
Behaviour of enabled novalidated constraint
Martin Vajsar, February 22, 2008 - 4:02 am UTC
Dear Tom,
if I have an enabled, but novalidated (and norely) check constraint on a table containing data that don't comply with the constraint, is there any risk that the database might return "bad" results, eg. because the optimizer might choose inapropriate access path or something similar? (The columns having the check condition on them are never used in where conditions, but I'd prefer to be absolutely sure.)
I have a table that currently contains invalid data and I want to deal with these over time, hovewer I'd like to prevent new data from entering the table. When all the records will be corrected, I'd just validate the constraints (the correcting of values must be actually done by the end users). Are constraints supposed to be used in this way?
February 22, 2008 - 7:15 am UTC
http://asktom.oracle.com/Misc/stuck-in-rut.html if the constraint is not validated, you have to tell us to trust you - if you never set query rewrite integrity to trusted, we won't trust you - and will pretend the constraint doesn't exists (from the optimizer point of view)
Integrity Constraints and Parallelism
Ying, April 03, 2008 - 12:01 am UTC
http://www.itk.ilstu.edu/docs/Oracle/server.101/b10736/constra.htm#i1006317 All constraints can be validated in parallel. When validating constraints on very large tables, parallelism is often necessary to meet performance goals. The degree of parallelism for a given constraint operation is determined by the default degree of parallelism of the underlying table.However, when we try to enable validate Referential constraints (FOREIGN KEY) after ETL process, parallel validation is NOT happening even we alter the underlying table parallel 16. We see only ONE process is running during the validation. Looks like FOREIGN KEY constraints can NOT be validated in parallel?
April 03, 2008 - 7:47 pm UTC
it can be validated during an enable in parallel, yes.
big_table%ORA10GR2> alter table big_table add constraint big_table_fk foreign key(owner) references big_table_owners(owner) enable novalidate;
Table altered.
big_table%ORA10GR2> @trace
big_table%ORA10GR2> alter session set events '10046 trace name context forever, level 12';
Session altered.
big_table%ORA10GR2> @mystat "queries parallel"
big_table%ORA10GR2> set echo off
NAME VALUE
---------------------- ----------
queries parallelized 0
big_table%ORA10GR2> alter table big_table modify constraint big_table_fk enable;
Table altered.
big_table%ORA10GR2> @mystat2
big_table%ORA10GR2> set echo off
NAME VALUE DIFF
---------------------- ---------- ------------------
queries parallelized 1 1
Integrity Constraints and Parallelism
A reader, April 04, 2008 - 10:24 pm UTC
Excellent. I still have one question. If I try to directly use:
alter table ... ENABLE VALIDATE CONSTRAINT ...I would NOT see it run in parallel.
Any reason a disabled FK constraint need to be 'enable novalidate' first before it can be validated in parallel?
Again, Thank you very much for your insight.
April 07, 2008 - 8:33 am UTC
it is just the "way it is"....
unqiue key disabled
satin, March 31, 2010 - 10:38 am UTC
Hello Tom,
I am searching for this online and could not find any topic related to this.I have created a partition table with global indexes on this.
First attempt ,One of ETL job is inserting via bulk load option first time we sucesfully inserted the data but ended up with table space issue.
Second attempt when i try to insert the records job aborted due to voilation of the unique records.Because of this unique index is went to unstable state
Thrid attempt ,it allowed the duplcates because unique index is disable and ended up with duplcates .
My question is Can it be possible if we try to insert to duplcates on partition table and index go on to unstable state. Otherwise what could be the reason
Integrity Constraints and Parallelism
A reader, June 20, 2013 - 4:21 pm UTC
June 20, 2013 - 8:05 pm UTC
it is not.
Integrity Constraints and Parallelism
A reader, June 20, 2013 - 8:35 pm UTC
Thanks Tom for your quick response.
I tested with:
ALTER SESSION FORCE PARALLEL DDL PARALLEL 8;
This did not really force parallel for my foreign key constraint validation. The validation was still serial for my test case.
So FORCE PARALLEL DDL only works for "other" DDLs?
Thanks!
June 20, 2013 - 8:40 pm UTC
Integrity Constraints and Parallelism
A reader, June 21, 2013 - 6:12 pm UTC
Hi Tom,
Suppose I want to use parallel 8 to do foreign key constrait validation.
To parallelize the validation of foreign key constraint, is it enough to only have the child table's default degree set to 8?
Do we need to set the parent table's default degree to 8 as well? Will Oracle handle the parallel validation operations differently if the default degree of the parent table is set to 1?
Thanks!
July 01, 2013 - 5:27 pm UTC
it is based on the table that you are validating the constraint upon. the parallel is based on the child table, not the parent.
Constraint Validation using parallel process
Rajeshwaran, July 07, 2013 - 10:22 am UTC
Tom:
I was running below script in 10.2.0.5 and 11.2.0.1 and found that parallel process happened in 11g but not in 10g database. Is this a new feature added in 11g database if yes do you have the doc link on this?
--Session#1 execution
alter table big_table parallel 4 ;
alter session enable parallel dml;
exec dbms_application_info.set_client_info('VALIDATE_CONSTRAINT');
alter table big_table
modify id constraint id_not_null
not null novalidate ;
alter table big_table
modify constraint id_not_null
validate;
--Session#2 execution
select sid,serial#,event,sql_id,
( select distinct sql_text from v$sql t1 where t1.sql_id = t2.sql_id ) sql_text,t2.last_call_et
from gv$session t2
where client_info='VALIDATE_CONSTRAINT';
Script execution's were updated in blog
http://rajeshwaranbtech.blogspot.in/2013/07/constraint-validation-in-parallel-seems.html
Constraint Validation using parallel process
Rajeshwaran, July 16, 2013 - 8:45 pm UTC
Tom:
Am I missing any thing in above question?
July 17, 2013 - 5:45 pm UTC
no, i just don't read them all. and if I cannot answer immediately off the top of my head when traveling, I skip some. It is very hit or miss. depends on how much time I have.
I just did a *very quick* test and the query:
select /*+ all_rows ordered */ A.rowid, :1, :2, :3
from
"BIG_TABLE"."BIG_TABLE" A where not ( "OWNER" IS NOT NULL)
that is generated for the constraint validation had a parallel plan in the trace file:
Rows Row Source Operation
------- ---------------------------------------------------
0 PX COORDINATOR (cr=145468 pr=145428 pw=0 time=3959908 us)
0 PX SEND QC (RANDOM) :TQ10000 (cr=145468 pr=145428 pw=0 time=3959900 us)
0 PX BLOCK ITERATOR (cr=145468 pr=145428 pw=0 time=3959895 us)
0 TABLE ACCESS FULL BIG_TABLE (cr=145468 pr=145428 pw=0 time=3959892 us)
that was 10.2.0.5 - so it seems it would definitely be possible. see also
http://timurakhmadeev.wordpress.com/2011/02/16/enabling-constraint-in-parallel/
Constraint Validation using parallel process
Rajeshwaran, July 17, 2013 - 8:49 pm UTC
Thanks Tom. I too got this in 10.2.0.5 Tkprof trace, but why there are not entries in v$px_session while this statement is running ?
select /*+ all_rows ordered */ A.rowid, :1, :2, :3
from
"RAJESH"."BIG_TABLE" A where not ( "ID" IS NOT NULL)
Parsing user id: 61 (recursive depth: 1)
Rows Row Source Operation
------- ---------------------------------------------------
0 PX COORDINATOR (cr=145999 pr=145476 pw=0 time=291297275 us)
0 PX SEND QC (RANDOM) :TQ10000 (cr=145999 pr=145476 pw=0 time=291297271 us)
0 PX BLOCK ITERATOR (cr=145999 pr=145476 pw=0 time=291297265 us)
0 TABLE ACCESS FULL BIG_TABLE (cr=145999 pr=145476 pw=0 time=291297261 us)
table_name in all_constraints..
Vikas Sharma, October 17, 2013 - 4:36 pm UTC
Hi Tom,
I encounter with one strange thing. I found a table_name in all_constraints which does not exists in all_table table_name for same schema. see below.
sql> select table_name from all_tables where owner='BAID_DL_IMP' order by table_name;
table_name
-------------
......
........
BANKRECO_TRAN
BANK_INTEREST
BANK_MAST
BILLAGE_TRAN
BILL_CATG_MAST
BOM_MAST
BS_MAST
CHALLAN_TRAN
sql> select table_name,constraint_type from all_constraints where owner='BAID_DL_IMP' and constraint_type='P' order by table_name
table_name constraint_type
--------------------------------
...........
..................
BANKRECO_TRAN P
BANK_MAST P
BILL_CATG_MAST P
BIN$1jKxqAm3Rj+XpleBlLSUmQ==$0 P << where it come from...
BOM_MAST P
BS_MAST P
CHALLAN_TRAN P
Actually i am trying to create an script to disable the pk constraints on all table. when i execute it it fails.
script query
--------------
select 'ALTER TABLE '||owner||'.'||table_name||' DISABLE CONSTRAINT '||constraint_name as sql_string,constraint_name,table_name,*
from all_constraints
where constraint_type='P'
and owner='BAID_DL_IMP' order by table_name
SQL> ALTER TABLE BAID_DL_IMP.BIN$1jKxqAm3Rj+XpleBlLSUmQ==$0 DISABLE CONSTRAINT
2 BIN$Kt8AaMGsQLe/XNE+XOL3+A==$0;
ALTER TABLE BAID_DL_IMP.BIN$1jKxqAm3Rj+XpleBlLSUmQ==$0 DISABLE CONSTRAINT
*
ERROR at line 1:
ORA-01735: invalid ALTER TABLE option
Vikas Sharma
November 01, 2013 - 8:13 pm UTC
that is a dropped table. It is in your recyclebin.