Today I ran into a strange Oracle situation. It took me some time to realize what it is, so I decided to write it as a challenge. Hope you will find it interesting.
I have 2 tables, A and B. Each table has indexes, constraints, many columns and more (But no triggers). Table A has the ID column (which is the primary key) and the NAME column (varchar2). Table B has the ID column (primary key) and the A_ID column (which is FK to table A).
What I tried to do is to delete a specific row from A:
SQL> delete from a where name='x'; delete from a where name='x' * ERROR at line 1: ORA-02292: integrity constraint (LIRON.B_FK) violated - child record found
As you can see I got the constraint violation error, which means there are child records in B, so I checked:
SQL> select * from b where a_id in (select id from a where name='x'); no rows selected
But there are no rows!
What’s going on here?
I will post the answer in a few days.
Good luck
I would say: you forgot to alias the tables
Alex, I didn’t understand what you mean…
Hi,
maybe because a VPD policy is defined on the child table b? E.g. if we take a setup like the one defined here http://www.adp-gmbh.ch/ora/security/vpd/ (and drop the FK from the employee table to simplify the test case), then:
SQL> connect frank/frank
Connected.
SQL> delete from test.department where name = ‘Sales’;
delete from test.department where name = ‘Sales’
*
ERROR at line 1:
ORA-02292: integrity constraint (TEST.SYS_C009998) violated – child record found
SQL> select * from test.department_secrets
2 where dep_id in (select dep_id from test.department where name = ‘Sales’);
no rows selected
Regards,
Jure
That’s a nice idea Jure. VPD can indeed cause this.
However, VPD was not in use in this case.
What about having invalid data in partitions, i.e. having data with a partition key that doesn’t belong to a certain partition and using an execution plan which allows partition pruning:
However, if partition pruning doesn’t occur as in the previous example, we get a different answer, since Oracle visits the table B by first obtaining the rowid from the global index on id_a:
Regards,
Jure
Something like this (please edit if the formatting tags don’t work):
Hi Jonathan,
I couldn’t reproduce it, what is the structure of the tables?
This is what I tried:
SQL> create table a (id number primary key, id1 number, name varchar2(10));
Table created.
SQL> create table b(id number primary key, a_id number, name varchar2(10));
Table created.
SQL> alter table b add constraint b_fk foreign key (a_id) references a;
Table altered.
SQL> insert into a values (1,1,’A’);
1 row created.
SQL> insert into a values (2,2,’x’);
1 row created.
SQL> insert into b values (1,2,’padding’);
1 row created.
SQL> commit;
Commit complete.
SQL> delete from a where name = ‘x’;
delete from a where name = ‘x’
*
ERROR at line 1:
ORA-02292: integrity constraint (LIRON.B_FK) violated – child record found
SQL> select * from b where a_id in (select id from a where name = ‘x’);
ID A_ID NAME
———- ———- ———-
1 2 padding
Like yours, it’s extra constraints on that you might overlook.
A has a PK on col1 and a UK on col2
B has two FKs to A, col1 to col1 and col2 to col2. The SYS-generated constraint names helped to obscure this.
Regards
Jonathan Lewis
Oh, I see.
Maybe I wasn’t clear enough, but I looked at the constraint name and checked which columns it is on before running the query from B looking for the missing child.
Cheers,
Liron