lets say I have table A and table B. Table B is the child table and has a foreign key to table A. I have other mirrored tables, lets say table C(mirror for table A) and table D(mirror for B). Both tables B and D have a foreign key to its respective table. I have created a trigger on table A in order when its inserted on table A, the trigger inserts the same on table C and the same for table B for table D. My doubt is that in the same transaction, I insert on tables A and B, and maybe the trigger for table B could execute first than the trigger for table A causing an error on table D because the parent foreign key is not found yet on table C. Can it happen and how can I fix it?.
That can't happen as you can't (normally) insert child record if its parent doesn't exist, so child table's trigger can't fire before master table's one.
SQL> create table table_a
2 (id_a number primary key,
3 name varchar2(10));
Table created.
SQL> create table table_b
2 (id_b number primary key,
3 id_a number references table_a (id_a),
4 address varchar2(10));
Table created.
This will fail because there's no parent record:
SQL> insert into table_b (id_b, id_a, address) values (1, 100, 'Croatia');
insert into table_b (id_b, id_a, address) values (1, 100, 'Croatia')
*
ERROR at line 1:
ORA-02291: integrity constraint (SCOTT.SYS_C00157817) violated - parent key not
found
Let's create parent first:
SQL> insert into table_a( id_a, name) values (100, 'Little');
1 row created.
OK; child can now be inserted:
SQL> insert into table_b (id_b, id_a, address) values (1, 100, 'Croatia');
1 row created.
Another option is to use deferrable foreign key constraint which lets you insert child records although parent doesn't exist. Control is done at the moment of commit
.
SQL> rollback;
Rollback complete.
SQL> drop table table_b;
Table dropped.
SQL> create table table_b
2 (id_b number primary key,
3 id_a number references table_a (id_a) initially deferred deferrable,
4 address varchar2(10));
Table created.
Inserting child record: now it works!
SQL> insert into table_b (id_b, id_a, address) values (1, 100, 'Croatia');
1 row created.
However, if I commit, error is being raised:
SQL> commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (SCOTT.SYS_C00157819) violated - parent key not
found
Is anything stored? Nope:
SQL> select * from table_b;
no rows selected
OK, so let's start over: child first:
SQL> insert into table_b (id_b, id_a, address) values (1, 100, 'Croatia');
1 row created.
Parent next (I didn't commit!):
SQL> insert into table_a( id_a, name) values (100, 'Little');
1 row created.
Commit at the end:
SQL> commit;
Commit complete.
Tables' contents:
SQL> select * from table_a;
ID_A NAME
---------- ----------
100 Little
SQL> select * From table_B;
ID_B ID_A ADDRESS
---------- ---------- ----------
1 100 Croatia
SQL>
Therefore, do the same: use deferrable constraints and you should be OK, regardless of triggers' firing sequence.