Альтернативным решением проблемы курицы и яйца является использование INSERT ALL. Поскольку это единственное утверждение, оно устраняет необходимость в отложенных ограничениях внешнего ключа. Он также предоставляет механизм для вставки точного количества зависимых строк. Дополнительные ограничения предотвращают вставку дополнительных строк. Но нам нужна вспомогательная таблица с внешними ключами, чтобы предотвратить случайное удаление интересующих строк.
В этом примере n = 3.
SQL> create table parent
2 ( pk_col number not null
3 , col1 varchar2(20)
4 , constraint par_pk primary key (pk_col)
5 )
6 /
Table created.
SQL>
SQL> create table child
2 ( pk_col number not null
3 , seqno number(1,0) not null
4 , col2 date
5 , constraint ch_pk primary key
6 (pk_col, seqno)
7 , constraint ch_par_fk foreign key
8 (pk_col) references parent (pk_col)
9 , constraint ch_ck check (seqno between 1 and 3)
10 )
11 /
Table created.
SQL>
SQL> create table child_lock
2 ( pk_col_1 number not null
3 , seqno_1 number(1,0) not null
4 , pk_col_2 number not null
5 , seqno_2 number(1,0) not null
6 , pk_col_3 number not null
7 , seqno_3 number(1,0) not null
8 , constraint chlk_pk primary key
9 (pk_col_1, seqno_1, pk_col_2, seqno_2, pk_col_3, seqno_3)
10 , constraint chlk_par_1_fk foreign key
11 (pk_col_1, seqno_1) references child (pk_col, seqno)
12 , constraint chlk_par_2_fk foreign key
13 (pk_col_2, seqno_2) references child (pk_col, seqno)
14 , constraint chlk_par_3_fk foreign key
15 (pk_col_3, seqno_3) references child (pk_col, seqno)
16 )
17 /
Table created.
SQL>
SQL> insert all
2 into parent values (pk_val, val_1)
3 into child values (pk_val, 1, sysdate)
4 into child values (pk_val, 2, sysdate+1)
5 into child values (pk_val, 3, sysdate+2)
6 into child_lock values (pk_val, 1, pk_val, 2, pk_val, 3)
7 select 999 as pk_val
8 , 'APPLE PIE' as val_1
9 from dual
10 /
5 rows created.
SQL>
SQL> insert into child values (999, 4, sysdate+4)
2 /
insert into child values (999, 4, sysdate+4)
*
ERROR at line 1:
ORA-02290: check constraint (APC.CH_CK) violated
SQL> insert into child values (999, 3, sysdate+4)
2 /
insert into child values (999, 3, sysdate+4)
*
ERROR at line 1:
ORA-00001: unique constraint (APC.CH_PK) violated
SQL> insert into child values (999, 2.5, sysdate+4)
2 /
insert into child values (999, 2.5, sysdate+4)
*
ERROR at line 1:
ORA-00001: unique constraint (APC.CH_PK) violated
SQL> delete from child
2 /
delete from child
*
ERROR at line 1:
ORA-02292: integrity constraint (APC.CHLK_PAR_1_FK) violated - child record found
SQL>
Я принимаю, что решение немного придумано и также негибко, но то же самое относится и к первоначальному требованию. Это также далеко от пуленепробиваемого - удалите строку из CHILD_LOCK, и вы можете удалить одну или несколько записей CHILD.