Reputation: 73
I am attempting to clean up some bad data from a DEV database (everyone has the ability to insert data for self testing) and add RI through foreign key constraints. The tables are set up for the FKs, however, the data is not.
Is there a relatively simple way to delete data from a (tobe) child table which would violate the composite keys?
CREATE TABLE parentTable
( key1 VARCHAR2(1) NOT NULL
, key2 VARCHAR2(1) NOT NULL
);
CREATE TABLE childTable
( key1 VARCHAR2(1) NOT NULL
, key2 VARCHAR2(1) NOT NULL
, key3 VARCHAR2(1) NOT NULL
);
ALTER TABLE parentTable ADD CONSTRAINT pk_parentTable primary key(key1,key2);
ALTER TABLE childTable ADD CONSTRAINT pk_childTable primary key(key1,key2,key3);
insert into parentTable values('0','A');
insert into parentTable values('0','B');
insert into parentTable values('1','C');
insert into childTable values('0','A','X');
insert into childTable values('0','B','Y');
insert into childTable values('1','C','X');
insert into childTable values('0','C','X'); -- bad data
The query I've been using to identify the bad data is as follows.
select distinct key1, key2 from childTable
minus
select distinct key1, key2 from parentTable;
How can I take this result set and delete them from child table. Logically I've attempted to use the following query below, but it gives an error of ORA-00928: missing SELECT.
with x as(
select distinct key1, key2 from childTable
minus
select distinct key1, key2 from parentTable
)
delete from childtable where key1 = x.key1 AND key2 = x.key2;
Is there another way to easily delete this data?
Upvotes: 1
Views: 823
Reputation: 3728
A possible solution is:
delete
from childTable
where not exists (select null
from parentTable
where childTable.key1 = parentTable.key1
and childTable.key2 = parentTable.key2);
Upvotes: 0
Reputation: 10541
Alternatively:
delete from childtable
where (key1,key2) not in
(select key1,key2 from parenttable)
Upvotes: 0
Reputation: 14393
Oracle actually has some built-in functionality to handle this.
First, run @?/rdbms/admin/utlexcpt.sql
to create the exceptions table.
Then, (attempt to) add the FK constraint, like this:
alter table childtable add constraint my_fk foreign key (key1,key2) references parenttable(key1,key2) exceptions into exceptions;
That will either complete, or it will error out. If it errors out, the row ids of the rows that violate the constraint will be in the exceptions table.
Then, it's a simple matter of executing:
delete from childtable where rowid in(select row_id from exceptions);
Then, just re-execute the alter table add constraint above.
More details can be found here: http://docs.oracle.com/cd/E11882_01/server.112/e41084/clauses002.htm#SQLRF52228
Hope that helps....
Upvotes: 1