此外,您可能希望在 cascade 子句中添加上述 cmets,因此如果您删除父行,所有相关的底层行也将被删除。下面是一个测试用例,慎用。
此外,我还提供了一个查询,您可能想用它来告诉您相关的内容。在我的示例中,我对表名“PARENT”进行了硬编码,但您可能希望使用绑定变量。祝你好运。
create table parent (
id NUMBER(10),
value varchar2(30),
constraint parent_pk primary key (id)
);
CREATE TABLE child
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint child_pk primary key (id,value),
CONSTRAINT parent_child_fk
FOREIGN KEY (id)
REFERENCES parent(id)
ON DELETE CASCADE
);
CREATE TABLE grandchild
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint grandchild_pk primary key (id,value),
CONSTRAINT child_grandchild_fk
FOREIGN KEY (id,value)
REFERENCES child(id,value)
ON DELETE CASCADE
);
insert into parent values (1,'a');
insert into parent values (2,'b');
insert into parent values (3,'c');
insert into child values (1,1);
insert into child values (1,2);
insert into child values (1,3);
insert into child values (2,1);
insert into child values (2,2);
insert into child values (2,3);
insert into child values (3,1);
insert into child values (3,2);
insert into child values (3,3);
insert into grandchild values (1,1);
insert into grandchild values (1,2);
insert into grandchild values (1,3);
insert into grandchild values (2,1);
insert into grandchild values (2,2);
insert into grandchild values (2,3);
insert into grandchild values (3,1);
insert into grandchild values (3,2);
insert into grandchild values (3,3);
SELECT (
SELECT COUNT(*)
FROM parent
) AS parent_cnt,
(
SELECT COUNT(*)
FROM child
) AS child_cnt,
(
SELECT COUNT(*)
FROM grandchild
) AS grandchild_cnt
FROM dual
PARENT_CNT CHILD_CNT GRANDCHILD_CNT
3 9 9
DELETE from parent where value = 'a';
SELECT (
SELECT COUNT(*)
FROM parent
) AS parent_cnt,
(
SELECT COUNT(*)
FROM child
) AS child_cnt,
(
SELECT COUNT(*)
FROM grandchild
) AS grandchild_cnt
FROM dual
PARENT_CNT CHILD_CNT GRANDCHILD_CNT
2 6 6
Here is a query you can use to show the relationships
with f as (
select constraint_name, table_name, r_constraint_name
from user_constraints
where constraint_type = 'R'
),
p as (
select constraint_name, table_name
from user_constraints
where constraint_type = 'P'
),
j (child_table, f_key, parent_table, p_key) as (
select f.table_name, f.constraint_name, p.table_name, f.r_constraint_name
from p join f on p.constraint_name = f.r_constraint_name
union all
select 'PARENT', (select constraint_name from p where table_name = 'PARENT'), null, null from dual
)
select level as lvl, j.*
from j
start with parent_table is null
connect by nocycle parent_table = prior child_table
order by lvl, parent_table, child_table;
LVL CHILD_TABLE F_KEY PARENT_TABLE P_KEY
1 PARENT PARENT_PK - -
2 CHILD PARENT_CHILD_FK PARENT PARENT_PK
3 GRANDCHILD CHILD_GRANDCHILD_FK CHILD CHILD_PK
所以现在当我们从父表中删除时,Oracle 将检查是否有 FK 引用父表的表,并会找到表子表。然后它将一一检查要删除的表父行是否在表子中具有子行。如果不是,它将删除该表父行。如果有子级 if 将检查 FK 操作,并且由于该 FK 具有 ON DELETE CASCADE,Oracle 将尝试删除该表的子行。那时它将(与表父表相同)检查是否有 FK 引用表子表的表,并会找到表孙子表。同样,如果要删除的表子行在表孙子中是否有子项,它将一一检查。如果不是,它将删除该表子行。如果有子级 if 将检查 FK 操作,并且由于该 FK 具有 ON DELETE CASCADE,Oracle 将尝试删除该表的孙行。由于表grandchild 没有子表,Oracle 将删除表grandchild、child 和parent 中的相应行。