Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle Unique Constraint with Expression

Does Oracle support constraints with expressions like so?

Notice Z = 'N'

ALTER TABLE A ADD CONSTRAINT U_A_KEY UNIQUE(X,Y,Z = 'N');

Is this Unique constraint possible?

Example:

INSERT INTO A VALUES('X','Y','N');  --OK
INSERT INTO A VALUES('X','Y','Y');  --OK
INSERT INTO A VALUES('X','Y','Y');  --OK
INSERT INTO A VALUES('X','Y','N');  --VOLIATION
like image 264
JARC Avatar asked Jan 10 '11 15:01

JARC


People also ask

Can unique key have multiple NULL values in Oracle?

A null is never equal (nor not equal) to any other null, hence, a unique constraint on a single attribute will allow as many null rows as you can stuff in there.

What is the difference between unique index and unique constraint in Oracle?

A constraint has different meaning to an index. It gives the optimiser more information and allows you to have foreign keys on the column, whereas a unique index doesn't.

How do I create a composite unique key in Oracle?

Defining Composite Unique Keys Oracle creates an index on the columns of a unique key, so a composite unique key can contain a maximum of 16 columns. To define a composite unique key, you must use table_constraint syntax rather than column_constraint syntax.

How do I find unique constraints in Oracle SQL Developer?

In Oracle, use the view user_constraints to display the names of the constraints in the database. The column constraint_name contains the name of the constraint, constraint_type indicates the type of constraint, and table_name contains the name of the table to which the constraint belongs.


2 Answers

Maybe this gives an idea

drop table tq84_n;

create table tq84_n (
   x number, 
   y number, 
   z varchar2(10)
);

create unique index tq84_n_x on tq84_n (
  case when z = 'N' then x || '-' || y 
       else null
  end
);

Later:

insert into tq84_n values (4,5, 'N');

insert into tq84_n values (9,6, 'Y');
insert into tq84_n values (9,6, 'Y');

insert into tq84_n values (4,5, 'Y');

insert into tq84_n values (4,5, 'N');

Last one throws:

ORA-00001: unique constraint (SPEZMDBA.TQ84_N_X) violated
like image 76
René Nyffenegger Avatar answered Sep 20 '22 13:09

René Nyffenegger


The simplest approach in this case is generally to create a function based index. Something like

CREATE UNIQUE INDEX u_a_key
    ON a( (CASE WHEN z = 'N' THEN x ELSE null END),
          (CASE WHEN z = 'N' THEN y ELSE null END) );

If z is not 'N', both CASE statements evaluate to NULL and Oracle doesn't have to store the x & y values in the index structure (making the index smaller). If z is 'N', the x & y values are both stored in the index and the index behaves just like any other compound index.

like image 32
Justin Cave Avatar answered Sep 22 '22 13:09

Justin Cave