Мне кажется, что ограничения могут сделать работу. Вам не нужны триггеры.
Вот как. Сначала создайте таблицы без каких-либо ограничений. Затем добавьте их, как первичного, так и внешнего ключа, которые будут deferrable
(в противном случае вы не сможете вставить строки, так как родительские ключи еще не существуют).
SQL> create table employee
2 (empid number,
3 fname varchar2(10),
4 storeid number
5 );
Table created.
SQL> create table store
2 (storeid number,
3 storename varchar2(20),
4 storemanager number
5 );
Table created.
SQL>
SQL> alter table employee add constraint pk_employee primary key (empid, storeid);
Table altered.
SQL> alter table store add constraint pk_store primary key (storeid);
Table altered.
SQL>
SQL> alter table store add constraint fk_store_emp foreign key (storemanager, storeid)
2 references employee (empid, storeid)
3 deferrable initially deferred;
Table altered.
SQL> alter table employee add constraint fk_emp_store foreign key (storeid)
2 references store (storeid)
3 deferrable initially deferred;
Table altered.
SQL>
Теперь давайте добавимнекоторые данные: начальная вставка в employee
будет в порядке, пока я не выполню фиксацию, а затем произойдет сбой, поскольку ее хранилище еще не существует:
SQL> insert into employee values (1, 'John' , 1);
1 row created.
SQL> commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (SCOTT.FK_EMP_STORE) violated - parent key not
found
SQL>
Но, если я не сделаю фиксацию и обратите вниманиек тому, что я ввожу (то есть, что ссылочная целостность поддерживается), все будет в порядке:
SQL> insert into employee values (1, 'John' , 1);
1 row created.
SQL> insert into employee values (2, 'Matt' , 2);
1 row created.
SQL> insert into store values (1, 'Santa Clara', 1);
1 row created.
SQL> insert into store values (2, 'San Francisco', 2); --> note 2 as STOREID
1 row created.
SQL> commit;
Commit complete.
SQL> select * From employee;
EMPID FNAME STOREID
---------- ---------- ----------
1 John 1
2 Matt 2
SQL> select * From store;
STOREID STORENAME STOREMANAGER
---------- -------------------- ------------
1 Santa Clara 1
2 San Francisco 2
SQL>
Видите? Все идет нормально.
Теперь я попытаюсь изменить таблицу STORE
и установить для ее менеджера значение John
, которое работает в storeid = 1
, что означает, что оно должно завершиться с ошибкой:
SQL> update store set storemanager = 1
2 where storeid = 2;
1 row updated.
SQL> commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (SCOTT.FK_STORE_EMP) violated - parent key not
found
SQL>
Как и ожидалось.
Давайте теперь добавим emplyoee ID = 6
, Jimmy
, который работает в storeid = 2
и назначим его менеджером в Сан-Франциско (storeid = 2
):
SQL> insert into employee values (6, 'Jimmy', 2);
1 row created.
SQL> update store set storemanager = 6
2 where storeid = 2;
1 row updated.
SQL> commit;
Commit complete.
SQL>
Yey! Это работает!
Как видите, триггеры не нужны.
Обратите внимание, что - если вы захотите удалить любую из этих таблиц - у вас не получится, так как на них ссылаются вседругое:
SQL> drop table store;
drop table store
*
ERROR at line 1:
ORA-02449: unique/primary keys in table referenced by foreign keys
SQL> drop table employee;
drop table employee
*
ERROR at line 1:
ORA-02449: unique/primary keys in table referenced by foreign keys
SQL>
Это означает, что сначала нужно удалить ограничения внешнего ключа, а затем таблицы:
SQL> alter table employee drop constraint fk_emp_store;
Table altered.
SQL> alter table store drop constraint fk_store_emp;
Table altered.
SQL> drop table store;
Table dropped.
SQL> drop table employee;
Table dropped.
SQL>
Вот и все, я думаю.