I am trying to insert 0 rows into a table that has a unique constraint and I am getting ORA-00001: unique constraint violated...
Below is the PL/SQL block I've used to hopefully capture the issue well
declare
l_cnt number;
begin
set transaction isolation level serializable;
select count(*) into l_cnt from test_view;
dbms_output.put_line('count = ' || to_char(l_cnt));
insert into <table>(<columns>)
select <columns> from test_view
log errors ('run1')
reject limit 0
;
dbms_output.put_line('success');
exception
when others then
dbms_output.put_line('ERRROR!');
dbms_output.put_line(sqlerrm);
rollback;
end;
/
This is the output
count = 0
ERRROR!
ORA-00001: unique constraint (<SCHEMA>.<CONSTRAINT>) violated
And sure enough, there is a record in the ERR$_<table> table...
If I add where 1 = 0 to the in the insert statement, everything works, nothing is inserted.
I still don't believe what I am seeing :)
Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production
Update 1
Below sample without using count(*) on the view as this could lead to a different query plan that selecting all required values for the insert.
declare
l_cnt number;
begin
set transaction isolation level serializable;
insert into testx_table
select * from testx_view d;
select count(*) into l_cnt from testx_table;
dbms_output.put_line('count = ' || to_char(l_cnt));
insert into <table>(<columns>)
select * from testx_view d
log errors ('run2')
reject limit 0;
dbms_output.put_line('success');
exception
when others then
dbms_output.put_line('ERRROR!');
dbms_output.put_line(sqlerrm);
rollback;
end;
/
UPDATE 2
I was able to reproduce the behaviour.
CREATE TABLE A(ID NUMBER PRIMARY KEY)
/
CREATE FUNCTION F(ID_ NUMBER) RETURN NUMBER
AS
L_ID NUMBER;
BEGIN
SELECT ID INTO L_ID FROM A WHERE ID = ID_;
RETURN L_ID;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END;
/
BEGIN
DBMS_ERRLOG.CREATE_ERROR_LOG('A');
END;
/
BEGIN
INSERT INTO A VALUES (1);
INSERT INTO A SELECT 1 FROM DUAL WHERE F(1) IS NULL
LOG ERRORS INTO ERR$_A;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
SELECT * FROM ERR$_A
/
And it all boils down to querying table that is being modified from within the function. The functions throws the ORA-04091: table A is mutating, trigger/function may not see it but the code catches all exceptions and returns null.
Obviously, selecting from table that's mutating is a nono and must be fixed.
And I am quite angry as I cannot count the number of times I told my collegues to stop using exception when others then return null. This is again an example where it completely masked the issue and I've spent the whole day deubgging it.
reject limit 0means that no errors are allowed, so obviously it will stop at the first error. Are you looking forreject limit unlimited? - a_horse_with_no_nameselect count(*). It is not so uncommon to get a wrongcount(*)due to corrupted index. You should also realize that you can't get a meaningfull response without showing some details of the view. E.g. I suspect if youselect *you see some data. - Marmite Bombercount(*)could give different results that selecting all the values. However, even when I insert all the data into a different table using exactly the same query I can see that there are 0 rows (see my updated question)... If I doselect * from testx_viewI see 0 records... - Petr