Home » SQL & PL/SQL » SQL & PL/SQL » Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE (Oracle 11g 11.2.0.4.0)
Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655710] Fri, 09 September 2016 08:45 Go to next message
fixxxer
Messages: 45
Registered: August 2014
Member
I am adding a unique constraint on a table with existing data which violates the unique constraint. New data being inserted will comply with the unique constraint, so I am creating it using:

ALTER TABLE my_table ADD CONSTRAINT my_table_ux1 UNIQUE (col1) DEFERRABLE INITIALLY DEFERRED NOVALIDATE;

This is working fine, but the index behind the unique constraint is being created in the default tablespace.

I couldn't see the syntax for specifying the tablespace to be used for the index.

Is this possible to do?

Thanks in advance - FIXXXER

Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655711 is a reply to message #655710] Fri, 09 September 2016 08:46 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
create the index before creating the constraint
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655712 is a reply to message #655711] Fri, 09 September 2016 09:28 Go to previous messageGo to next message
fixxxer
Messages: 45
Registered: August 2014
Member
Brilliant, thank you very much!
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655713 is a reply to message #655712] Fri, 09 September 2016 09:30 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
drop the index & recreate it where you want it to reside.
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655714 is a reply to message #655713] Fri, 09 September 2016 09:42 Go to previous messageGo to next message
fixxxer
Messages: 45
Registered: August 2014
Member
BlackSwan wrote on Fri, 09 September 2016 15:30
drop the index & recreate it where you want it to reside.
I went with the first suggestion, creating the index in the first place, then the unique constraint! Works perfect, thanks!
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655715 is a reply to message #655710] Fri, 09 September 2016 10:47 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
SQL> create table t (val int);

Table created.

SQL> insert into t select 0 from dual connect by level<=3;

3 rows created.

SQL> commit;

Commit complete.

SQL> select * from t;
       VAL
----------
         0
         0
         0

3 rows selected.

SQL> select default_tablespace from user_users;
DEFAULT_TABLESPACE
------------------------------
TS_D01

1 row selected.
Theoretically the following syntax is valid but a bug in the syntax analyzer (in all Oracle versions) aborts it:
SQL> alter table t add constraint t_unq unique(val)
  2  DEFERRABLE INITIALLY DEFERRED NOVALIDATE
  3  using index (create index t_unq on t(val) tablespace ts_i01)
  4  /
using index (create index t_unq on t(val) tablespace ts_i01)
*
ERROR at line 3:
ORA-01735: invalid ALTER TABLE option
Otherwise it'd create the index and put it in the correct tablespace, in fact it is the NOVALIDATE part that hurts:
SQL> alter table t add constraint t_unq unique(val)
  2  DEFERRABLE INITIALLY DEFERRED -- NOVALIDATE
  3  using index (create index t_unq on t(val) tablespace ts_i01)
  4  /
alter table t add constraint t_unq unique(val)
                             *
ERROR at line 1:
ORA-02299: cannot validate (MICHEL.T_UNQ) - duplicate keys found
You can't even not workaroond the problem creating the constraint in DISABLE state to then ENABOE NOVALIDATE it because DISABLE leads to the same error:
SQL> alter table t add constraint t_unq unique(val)
  2  DEFERRABLE INITIALLY DEFERRED disable -- NOVALIDATE
  3  using index (create index t_unq on t(val) tablespace ts_i01)
  4  /
using index (create index t_unq on t(val) tablespace ts_i01)
*
ERROR at line 3:
ORA-01735: invalid ALTER TABLE option
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655716 is a reply to message #655715] Fri, 09 September 2016 10:56 Go to previous messageGo to next message
fixxxer
Messages: 45
Registered: August 2014
Member
Great information on this MC, thanks for that!

This is a one time activity so thankfully the 2 step process suggested by blackswan will work well!
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655717 is a reply to message #655716] Fri, 09 September 2016 11:18 Go to previous messageGo to next message
Bill B
Messages: 1971
Registered: December 2004
Senior Member
Also, why not simply do an ALTER INDEX with the rebuild option which allows you to specify the tablespace.
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655718 is a reply to message #655717] Fri, 09 September 2016 11:24 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Maybe there is not enough space in the first tablespace, also why waste time and spend resources to first create an index in the wrong tablespace. Wink

Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655719 is a reply to message #655718] Fri, 09 September 2016 11:39 Go to previous messageGo to next message
Bill B
Messages: 1971
Registered: December 2004
Senior Member
I was not suggesting that you use rebuild as a matter of course, I was saying that in this case where they already have an existing index simply use rebuild to move it to the correct tablespace instead of dropping and rebuilding the index in the correct location. That being said, you should always create the non unique index in the correct tablespace and enforce it with the DEFERRABLE INITIALLY DEFERRED NOVALIDATE constraint.
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655720 is a reply to message #655719] Fri, 09 September 2016 11:50 Go to previous messageGo to next message
fixxxer
Messages: 45
Registered: August 2014
Member
Bill B wrote on Fri, 09 September 2016 17:39
I was not suggesting that you use rebuild as a matter of course, I was saying that in this case where they already have an existing index simply use rebuild to move it to the correct tablespace instead of dropping and rebuilding the index in the correct location. That being said, you should always create the non unique index in the correct tablespace and enforce it with the DEFERRABLE INITIALLY DEFERRED NOVALIDATE constraint.
Hi Bill, the index does not exist at the minute, it is a new index.
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655723 is a reply to message #655715] Fri, 09 September 2016 16:26 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Michel Cadot wrote on Fri, 09 September 2016 11:47

Theoretically the following syntax is valid
No, it isn't. Correct syntax is:

SQL> alter table t add constraint t_unq unique(val)
  2  DEFERRABLE INITIALLY DEFERRED
  3  using index (create index t_unq on t(val) tablespace users)
  4  NOVALIDATE
  5  /

Table altered.

SQL>

SY.
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655731 is a reply to message #655715] Fri, 09 September 2016 21:49 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Michel Cadot wrote on Fri, 09 September 2016 11:47
[code]
You can't even not workaroond the problem creating the constraint in DISABLE state to then ENABOE NOVALIDATE it because DISABLE leads to the same error:
Incorrect sequence of clauses again. ENABLE/DISABLE, same as VALIDATE/NOVALIDATE must follow USING clause while DEFERRABLE INITIALLY DEFERRED must precede it:

SQL> alter table t add constraint t_unq unique(val)
  2  DEFERRABLE INITIALLY DEFERRED
  3  using index (create index t_unq on t(val) tablespace users)
  4  DISABLE
  5  /

Table altered.

SQL>

It is all in syntax diagram:

[ [ [ NOT ] DEFERRABLE ]
  [ INITIALLY { IMMEDIATE | DEFERRED } ]
| [ INITIALLY { IMMEDIATE | DEFERRED } ]
  [ [ NOT ] DEFERRABLE ]
]
[ RELY | NORELY ]
[ using_index_clause ]
[ ENABLE | DISABLE ]
[ VALIDATE | NOVALIDATE ]
[ exceptions_clause ]

SY.
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655733 is a reply to message #655731] Sat, 10 September 2016 00:45 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Syntax diagram is:
/forum/fa/13257/0/
which means you can give the elements in any order.
When order matters the syntax is like the following one:
/forum/fa/13258/0/

Anyway, thanks to give a syntax which works and the solution to this mystery that Oracle people can't answer when I asked them: the bug is in the syntax diagram.

Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655738 is a reply to message #655733] Sat, 10 September 2016 05:57 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
I always look at non-graphical diagrams.

SY.
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655740 is a reply to message #655738] Sat, 10 September 2016 11:43 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

A link to where you got this would be welcome.

Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655742 is a reply to message #655740] Sat, 10 September 2016 15:04 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
I had previously encountered this problem and up until what Solomon posted in this thread, I also thought it was a bug.

I have noticed that under each syntax picture, there is an option immediately below to click on the description of the syntax, but had never paid much attention to it.

If you go to constraints:

http://docs.oracle.com/database/121/SQLRF/clauses002.htm#SQLRF52180

and scroll down until you see:

constraint_state::=

then just below that, click on:

Description of the illustration ''constraint_state.gif''

you get the "non-graphical diagram" that Solomon posted:

http://docs.oracle.com/database/121/SQLRF/img_text/constraint_state.htm
Re: Unique Constraint With DEFERRABLE INITIALLY DEFERRED NOVALIDATE [message #655743 is a reply to message #655742] Sun, 11 September 2016 00:48 Go to previous message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Thanks for the trick.

Previous Topic: Format result set of a union
Next Topic: Problems converting String to data
Goto Forum:
  


Current Time: Wed Apr 24 21:07:39 CDT 2024