Удалить дочернюю и родительскую строку одним скриптом SQL - PullRequest
17 голосов
/ 10 марта 2012

Вместо того, чтобы удалить дочернюю строку и затем написать другую инструкцию sql для удаления родительской строки, я хотел использовать одну инструкцию, которая будет выполнять обе задачи. К вашему сведению: мы используем базу данных Oracle.

Обновление: У меня нет привилегии делать DELETE ON CASCADE

Ответы [ 7 ]

14 голосов
/ 10 марта 2012

Определите ваши внешние ключи с помощью каскадного удаления . Тогда вам нужно только удалить «родительскую» строку.

4 голосов
/ 18 сентября 2014
delete from 
(
select * from parent join child using (id)
where id = 1
)

ВНИМАНИЕ!Удаляет только там, где существуют родительские и дочерние строки.НЕ удалит родителей без детей

2 голосов
/ 10 марта 2012

Вы можете сделать это только плохо - то есть, используя триггеры.

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 голос
/ 10 марта 2012

Если вы всегда хотите удалять дочерние элементы при удалении родительской строки, вы можете объявить ограничение внешнего ключа, чтобы 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 голосов
/ 08 июня 2019

После нескольких действительно неудачных попыток решить эту проблему на относительно большой и чрезвычайно важной базе данных я решил сделать для нее Серебряную пулю ! потому что я не смог найти любой ! На самом деле, ни одно из решений / ответов в этой теме не соответствует потребностям проблемы.

См. CASCADELETE РЕПО на моем github.

0 голосов
/ 01 мая 2019

В случае, если это кому-нибудь поможет, я просто написал скрипт PLSQL, чтобы сделать это для всех ограничений внешнего ключа в таблице с некоторой помощью из этого вопроса Stackoverflow .Надеюсь, это поможет.

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 голосов
/ 10 марта 2012

Другой (скучно, у нас это есть в базе данных, которая по неизвестной причине не использует внешние ключи в качестве ограничений - да, да), чтобы сделать это, было бы создать триггер после (или до) удаления.

Вам придется написать еще один запрос на удаление, но только в триггере.

Но если вы не можете поставить каскад удаления, я не уверен, что вы можете добавить триггеры ...

...