So my assumption is, that the loader is too fast, and the trigger is
not
finished with doing it's work before the next row tries to insert.
Is
that possible? Or does anyone know a workaround?
Lets say you have the following:
drop table t;
create table t ( x int );
create or replace trigger t_trigger
before insert on t
for each row
declare
l_cnt number;
begin
select count(*) into L_cnt from t where x = :new.x;
end;
/
If you insert 1 row, you'll succeed as follows:
SQL> insert into t values ( 1 );
1 row created.
But if you insert >1 row, if fails:
SQL> insert into t select 1 from dual union all select 1 from dual;
insert into t select 1 from dual union all select 1 from dual
*
ERROR at line 1:
ORA-04091: table TKYTE.T is mutating, trigger/function may not see
it
ORA-06512: at "TKYTE.T_TRIGGER", line 4
ORA-04088: error during execution of trigger 'TKYTE.T_TRIGGER'
This is the documented behaviour of INSERT/FOR EACH ROW triggers (in
the
applications developers guide, you can read about it).
So, how to work around with sqlldr? If I take a control file like:
LOAD DATA
INFILE *
INTO TABLE T
REPLACE
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(X)
BEGINDATA
1
1
1
1
1
1
-------------- eof -------------
and just run:
$ sqlldr tkyte/tkyte x.ctl
I'll get:
Record 2: Rejected - Error on table T.
ORA-04091: table TKYTE.T is mutating, trigger/function may not see
it
ORA-06512: at "TKYTE.T_TRIGGER", line 4
ORA-04088: error during execution of trigger 'TKYTE.T_TRIGGER'
Record 4: Rejected - Error on table T.
ORA-04091: table TKYTE.T is mutating, trigger/function may not see
it
ORA-06512: at "TKYTE.T_TRIGGER", line 4
ORA-04088: error during execution of trigger 'TKYTE.T_TRIGGER'
Record 6: Rejected - Error on table T.
ORA-04091: table TKYTE.T is mutating, trigger/function may not see
it
ORA-06512: at "TKYTE.T_TRIGGER", line 4
ORA-04088: error during execution of trigger 'TKYTE.T_TRIGGER'
Table T:
3 Rows successfully loaded.
3 Rows not loaded due to data errors.
0 Rows not loaded because all WHEN clauses were failed.
0 Rows not loaded because all fields were null.
in my log file (every other record failed). If instead I execute:
$ sqlldr tkyte/tkyte x.ctl rows=1
Table T:
6 Rows successfully loaded.
0 Rows not loaded due to data errors.
0 Rows not loaded because all WHEN clauses were failed.
0 Rows not loaded because all fields were null.
I get them all loaded. sqlldr batches them up and inserts >1 per
statement --
that causes the mutating trigger error. If sqlldr loads 1 row
at a time -- no
error.
hope this helps...
Thomas Kyte
[email protected]
Oracle Service Industries
Reston, VA USA