Oracle删除会违反要添加的外键的数据

时间:2013-10-30 06:10:21

标签: database oracle foreign-keys sql-delete

我正在尝试清理DEV数据库中的一些不良数据(每个人都可以插入数据进行自我测试)并通过外键约束添加RI。这些表是为FK设置的,但数据不是。

是否有一种相对简单的方法从(tobe)子表中删除会违反复合键的数据?

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

我用来识别错误数据的查询如下:

select distinct key1, key2 from childTable
  minus 
  select distinct key1, key2 from parentTable;

如何获取此结果集并从子表中删除它们。从逻辑上讲,我试图使用下面的查询,但它给出了ORA-00928的错误:缺少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; 

还有其他方法可以轻松删除这些数据吗?

3 个答案:

答案 0 :(得分:1)

Oracle实际上有一些内置功能来处理这个问题。

首先,运行@?/rdbms/admin/utlexcpt.sql以创建例外表。

然后,(尝试)添加FK约束,如下所示:

alter table childtable add constraint my_fk foreign key (key1,key2) references parenttable(key1,key2) exceptions into exceptions;

那将完成,否则会出错。如果错误输出,则违反约束的行的行ID将位于例外表中。

然后,这是一个简单的执行问题:

delete from childtable where rowid in(select row_id from exceptions);

然后,只需重新执行上面的alter table add约束。

更多细节可以在这里找到: http://docs.oracle.com/cd/E11882_01/server.112/e41084/clauses002.htm#SQLRF52228

希望有所帮助....

答案 1 :(得分:0)

可替换地:

delete from childtable 
where (key1,key2) not in 
    (select key1,key2 from parenttable)

答案 2 :(得分:0)

可能的解决方案是:

delete
  from childTable
 where not exists (select null
                     from parentTable
                    where childTable.key1 = parentTable.key1
                      and childTable.key2 = parentTable.key2);