Suppose I have the following table with the following constraints:
create table test as (
select 1 as id, 'a' as name from dual
union all
select 2, 'b' from dual
union all
select 3, 'c' from dual
);
create unique index ind on test(name);
alter table test add constraint constr unique (name);
select * from test;
ID NAME
---------- ----
1 a
2 b
3 c
Suppose now that I do the following MERGE
:
merge into test t using (
select 4 as id, 'b' as name from dual
union all
select 2 as id, null as name from dual
) s on (s.id = t.id)
when matched then update set t.name = s.name
when not matched then insert(t.id, t.name) values(s.id, s.name)
select * from test;
ID NAME
---------- ----
1 a
2
3 c
4 b
Will the above MERGE
ever fail? If it UPDATE
s first, and then INSERT
s, the index/constraint will not be invalidated during execution. But if it first INSERT
s, and then UPDATE
s, the index will be temporary invalidated and the statement might fail?.
Can someone explain in detail (or point in the right direction) how Oracle RDBMS handles such issues? Furthermore, is the handling the same when using the LOG ERRORS INTO
clause?
Main reason why I ask this question and why I need a solution: I have MERGE statements running for several hours with LOG ERRORS INTO clause. The error logging seems to work as an autonomous transaction. Some unique constraint errors (based on unique indexes) are logged far before the statement finishes upserting (among others, I see the sequence going up), and I do not know why (although in the end, after upserting, no unique constraint should be invalidated). When I look into the ERROR table, I see ORA-00001: unique constraint (XXX.YYY) violated on an INSERT operation. I can insert this record from the ERROR table into main table without causing unique constraint failure. So I wonder why the error is logged in the first place.
EDIT: The answers below assert that when a statement is executed, the constraints are enforced at the end of the statement. I understand and agree (while I would like to know more details about index maintenance in such scenarios). What I do not understand and why this question is still not answered is why I am having these ORA-00001: unique constraint (XXX.YYY) violated errors logged while they should not be. Seems like the error logging mechanism doesn't behave in an atomic way.
EDIT2:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
EDIT3: I played a bit and was able to reproduce this error:
drop table test;
drop table err_test;
create table test as (
select 1 as id, 'a' as name from dual
union all
select 2, 'b' from dual
union all
select 3, 'c' from dual
);
create unique index ind on test(name);
alter table test add constraint constr unique (name);
--select test.rowid, test.* from test;
BEGIN
DBMS_ERRLOG.CREATE_ERROR_LOG (
dml_table_name => 'TEST',
err_log_table_name => 'ERR_TEST');
END;
/
--truncate table err_test;
select * from err_test;
merge /*+ PARALLEL(t 2) */ into test t using (
select 4 as id, 'b' as name from dual
union all
select 2 as id, null as name from dual
) s on (s.id = t.id)
when matched then update set t.name = s.name
when not matched then insert(t.id, t.name) values(s.id, s.name)
LOG ERRORS INTO ERR_TEST('TEST,ID:'||s.id) REJECT LIMIT UNLIMITED;
select * from err_test;
In the last select * from err_test;
I always get: ORA-00001: unique constraint (XXX.CONSTR) violated
. Now the strange thing is that the real MERGE statement (in production) doesn't work in PARALLEL any more, and I still get this error sometimes...
EDIT4: The best answer I have marked as accepted, although the question itself is not answered completely. It seems it is just a bug in Oracle.
This merge never fails.
This is explained with examples here: Database Concepts - 5. Data Integrity
For a not defferrable constrains (default):
The above means, that constraints are checked at the end of the entire single SQL statement, but not during their execution.
Below, in this documentation, you can find two examples of transactions, that "internally", during their execution, violate some constraint rules, but at the end they fulfill all constraint, and there are legal, because:
In the end they also wrote that: