我有两个表,一个父表和一个子表,它们在两个表之间声明了引用完整性,并尝试移动这两个表,以便我可以删除行。
我从子表开始,移动工作正常,行被删除。然后我尝试在父表上移动,移动失败。
我可以删除外键并完成父表上的移动,从而使父表和子表中的行数相同,这是我所期望的。
我不明白为什么父表上的移动失败,因为没有子引用。
我发现有趣的是,如果我ON CASCADE DELETE
在父表和子表上都设置了删除,只需在父表上删除即可。
有人可以向我解释为什么即使没有子行,父级的移动也会失败。我原以为这会奏效。
我在 Oracle 19.2 上运行,还使用 LIVESQL 对其进行了测试。下面是我的详细测试用例。
create table parent
as
select *
from all_objects
where rownum <= 10000;
alter table parent add constraint par_pk primary key(object_id);
create table child
as
select *
from parent
order by dbms_random.value;
alter table child add constraint chi_pk primary key(object_id);
alter table child add constraint chi_fk_par foreign key(object_id) references parent;
我已经从父数据创建了子表,随机排序。现在我将删除所有owner = ‘PUBLIC’
使用在线移动的子行,然后我将尝试对父行执行相同的操作。
SELECT count(*) from child
COUNT(*)
10000
alter table child move
including rows where owner != 'PUBLIC'
online
;
子移动成功
SELECT count(*) from child
COUNT(*)
4014
alter table parent move
including rows where owner != 'PUBLIC'
online
;
尝试对父级进行匹配移动会导致:
ORA-02266: 表中由启用的外键引用的唯一键/主键
现在,当我删除外键并进行移动时,一切似乎都可以正常工作。
alter table child disable CONSTRAINT chi_fk_par;
alter table parent move
including rows where owner != 'PUBLIC'
online
;
SELECT count(*) from parent
COUNT(*)
4014
alter table child enable CONSTRAINT chi_fk_par;
它失败是因为有外键,而不是因为完整性:移动是 DDL,而不是 DML。
您正在对其 PK 由 FK 引用的表使用过滤条件。
来自Oracle 文档