Oracle constraint to allow particular value once per foreign key value Oracle constraint to allow particular value once per foreign key value oracle oracle

Oracle constraint to allow particular value once per foreign key value


You can do it with a unique index:

create unique index initialindex on child(  case when is_initial <> 1 then parent_id || 'xx' || child_id        else null  end);

Now after you try to insert a second row with is_initial = 1 you should get a constraint violation.


Here you go, I believe I understand what you are looking for now

Note the change in the unique index:

create unique index childTable_initialIndex on childTable(  case when is_initial = 1 then parent_id   else null  end);

Ammended Code

create table childTable(parent_id number, child_id number primary key, is_initial number, somethingelse varchar2(50) );create unique index childTable_initialIndex on childTable(  case when is_initial = 1 then parent_id   else null  end);  insert into childTable(parent_id, child_id, is_initial,somethingelse) values (1,1,0,'works');1 rows inserted.    insert into childTable(parent_id, child_id, is_initial,somethingelse) values (1,1,0,'will not work if childId is pk');SQL Error: ORA-00001: unique constraint (SYS_C0062138) violated00001. 00000 -  "unique constraint (%s.%s) violated"*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.           For Trusted Oracle configured in DBMS MAC mode, you may see           this message if a duplicate entry exists at a different level.*Action:   Either remove the unique restriction or do not insert the key    insert into childTable(parent_id, child_id, is_initial,somethingelse) values (1,2,1,'works3');1 rows inserted.    insert into childTable(parent_id, child_id, is_initial,somethingelse) values (1,3,1,'should not work');SQL Error: ORA-00001: unique constraint (CHILDTABLE_INITIALINDEX) violated00001. 00000 -  "unique constraint (%s.%s) violated"*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.           For Trusted Oracle configured in DBMS MAC mode, you may see           this message if a duplicate entry exists at a different level.*Action:   Either remove the unique restriction or do not insert the key.    insert into childTable(parent_id, child_id, is_initial,somethingelse) values (2,4,0,'works4');1 rows inserted.  insert into childTable(parent_id, child_id, is_initial,somethingelse) values (2,5,0,'works5');1 rows inserted.  insert into childTable(parent_id, child_id, is_initial,somethingelse) values (2,6,1,'works6');1 rows inserted.  insert into childTable(parent_id, child_id, is_initial,somethingelse) values (2,7,1,'should not work');SQL Error: ORA-00001: unique constraint (CHILDTABLE_INITIALINDEX) violated00001. 00000 -  "unique constraint (%s.%s) violated"*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.           For Trusted Oracle configured in DBMS MAC mode, you may see           this message if a duplicate entry exists at a different level.*Action:   Either remove the unique restriction or do not insert the key.    --we should only see things that work  select * from childTable/ --this should not work, since works already has the 1/1 is_initial 1update childTable    set somethingelse = 'Should not work!'     , is_initial    = 1 where somethingelse = 'works';SQL Error: ORA-00001: unique constraint (CHILDTABLE_INITIALINDEX) violated00001. 00000 -  "unique constraint (%s.%s) violated"*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.           For Trusted Oracle configured in DBMS MAC mode, you may see           this message if a duplicate entry exists at a different level.*Action:   Either remove the unique restriction or do not insert the key.

Here are the results:

PARENT_ID CHILD_ID IS_INITIAL SOMETHINGELSE                                    --------- -------- ---------- --------------------------------------------------        1        1          0 works                                                      1        2          1 works3                                                     2        4          0 works4                                                     2        5          0 works5                                                     2        6          1 works6  


Do it in a more "relational" way - don't use child.is_initial, instead use parent.initial_child_id that can be NULL, and is FOREIGN KEY toward the child table.

Since initial_child_id is in the parent table and not in the child, there can naturally be only one per parent.

Your DDL would look something like this:

CREATE TABLE parent (    id INT,    initial_child_id INT,    PRIMARY KEY (id));CREATE TABLE child (    child_id INT,    parent_id INT NOT NULL,    PRIMARY KEY (child_id));ALTER TABLE parent ADD FOREIGN KEY (initial_child_id) REFERENCES child;ALTER TABLE child ADD FOREIGN KEY (parent_id) REFERENCES parent;