使用一个SQL脚本删除子行和父行

问题描述 投票:17回答:7

而不是删除子行,然后编写另一个sql语句来删除父行,我想使用一个语句来执行这两个操作。仅供参考:我们使用Oracle数据库。

更新:我没有权限执行DELETE ON CASCADE

sql oracle parent parent-child
7个回答
14
投票

使用cascading deletes定义外键。然后你只需要删除“父”行。


4
投票
delete from 
(
select * from parent join child using (id)
where id = 1
)

警告!仅删除父行和子行所在的位置。不会删除没有孩子的父母


2
投票

你只能做得很糟糕 - 即使用触发器。

create table parent
(pid number,
   constraint parent_pk
     primary key (pid)
     using index
);

create table child
  (cid number,
   pid number,
   constraint child_pk
     primary key(cid)
     using index,
   constraint child_fk
     foreign key (pid)
     references parent (pid)
  );

create index child_fk on child (pid);

create trigger fake_delete_cascade
before delete on parent
for each row
begin
  delete from child where pid = :old.pid;
end;
/

insert into parent values (1);
insert into child values (1,1);
commit;
select count(*) from child;
delete from parent where pid = 1;
select count(*) from child;

1
投票

如果您总是希望在删除父行时删除子项,则可以声明外键约束,以便Oracle自动删除子项

create table parent (
  parentID number primary key,
  parentData varchar2(100)
);

create table child (
  childID number primary key,
  parentID number references parent( parentID ) on delete cascade,
  childData varchar2(100)
);

例如,将声明父表和子表,并在删除父行时自动删除子行。如果您不希望自动强制执行此类操作,或者您不喜欢在后台“自动”发生事件时添加的复杂性,那么您可能会使用多个DELETE语句。


0
投票

另一种(无聊的方式,我们在一个数据库中有这个,由于未知的原因,不使用外键作为约束 - 是的)这样做是在删除之后(或之前)创建一个触发器。

您必须编写另一个删除查询,但只需在触发器中。

但如果你不能把删除级联,我不确定你可以添加触发器...


0
投票

如果它可以帮助其他人,我只是在this Stackoverflow question的帮助下编写了一个PLSQL脚本来为表中的所有外键约束执行此操作。希望能帮助到你。

DECLARE
  CURSOR constraint_cursor IS SELECT *
                              FROM (SELECT a.table_name,
                                           a.constraint_name,
                                           a.column_name,
                                           c_pk.table_name r_table_name,
                                           b.column_name   r_column_name
                                    FROM user_cons_columns a
                                           JOIN user_constraints c ON a.owner = c.owner
                                                                        AND a.constraint_name = c.constraint_name
                                           JOIN user_constraints c_pk ON c.r_owner = c_pk.owner
                                                                           AND
                                                                         c.r_constraint_name = c_pk.constraint_name
                                           JOIN user_cons_columns b ON C_PK.owner = b.owner
                                                                         AND
                                                                       C_PK.CONSTRAINT_NAME = b.constraint_name AND
                                                                       b.POSITION = a.POSITION
                                    WHERE c.constraint_type = 'R'
                                      and c_pk.owner = 'YOUR SCHEMA HERE') tbl;
  sql_statement VARCHAR2(2048) := NULL;
  tab_row       constraint_cursor%rowtype;
BEGIN
  OPEN constraint_cursor;
  FOR i in 1..80 LOOP
    FETCH constraint_cursor into tab_row;
    EXECUTE IMMEDIATE 'ALTER table ' || tab_row.table_name || ' drop constraint ' || tab_row.constraint_name;
    EXECUTE IMMEDIATE 'ALTER table ' || tab_row.table_name || ' add constraint ' || tab_row.constraint_name || ' FOREIGN KEY (' ||
    tab_row.column_name || ') references ' || tab_row.r_table_name || '(' || tab_row.r_column_name || ') ON DELETE CASCADE ';
  end loop;
  close constraint_cursor;
end;

0
投票

在一个相对较大且极其关键的数据库上遇到这个问题的一些非常糟糕的经历后,我决定为它制作一个Silver bullet!因为我找不到any!实际上,该线程中的解决方案/答案都不能满足问题的需要。

请参阅我的github上的CASCADELETE repo。

© www.soinside.com 2019 - 2024. All rights reserved.